-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUtil.hs
65 lines (51 loc) · 1.73 KB
/
Util.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
module Util where
import Control.Arrow ((&&&))
import Control.Monad ((>=>))
import Data.Function (on)
import Data.List (groupBy)
wordsBy :: (a -> Bool) -> [a] -> [[a]]
wordsBy f s = case dropWhile f s of
[] -> []
s' -> w : wordsBy f s''
where (w, s'') = break f s'
wordsOn :: (Eq a) => a -> [a] -> [[a]]
wordsOn x = wordsBy (== x)
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n l
| n > 0 = take n l : chunksOf n (drop n l)
| otherwise = error "Negative or zero n"
listToTuple :: [a] -> (a, a)
listToTuple [x, y] = (x, y)
listToTuple _ = error "list does not have exactly 2 elems"
prod :: [a] -> [b] -> [(a, b)]
prod a b = [(x, y) | x <- a, y <- b]
applyNTimes :: Int -> (a -> a) -> a -> a
applyNTimes n f = foldr (.) id (replicate n f)
applyNTimesM :: (Monad m) => Int -> (a -> m a) -> a -> m a
applyNTimesM n f = foldr (>=>) return (replicate n f)
fmapWithTag :: Functor f => (a -> b) -> f a -> f (a, b)
fmapWithTag f = fmap (id &&& f)
-- https://hackage.haskell.org/package/zippers-0.3.2/docs/src/Control.Zipper.Internal.html#farthest
farthest :: (a -> Maybe a) -> a -> a
farthest f = go where
go a = maybe a go (f a)
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:_) = Just x
safeAt :: Int -> [a] -> Maybe a
safeAt _ [] = Nothing
safeAt 0 (x:xs) = Just x
safeAt n (_:xs) = safeAt (n - 1) xs
median :: [a] -> a
median xs
| null xs = error "Can't find median of empty list"
| even (length xs) = error "Can't find median of even length list"
| otherwise = let
l = length xs
m = l `div` 2
in xs !! m
converge :: (Eq a) => (a -> a) -> a -> a
converge f x = let x' = f x in (if x == x' then x else converge f x')
groupOn :: (Eq b) => (a -> b) -> [a] -> [[a]]
groupOn f = groupBy ((==) `on` f)