-
Notifications
You must be signed in to change notification settings - Fork 0
/
List.hs
127 lines (105 loc) · 4.23 KB
/
List.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
module List where
import Control.Applicative
import Data.Char (digitToInt)
import Data.Universe.Helpers (diagonal)
import Data.List (nub)
-- implementation of parseInt
parseInt :: String -> Int
parseInt ('-':cs) = negate $ parseInt cs
parseInt cs = foldl (\t c -> 10 * t + digitToInt c) 0 cs
-- python range (but inclusive)
range :: Integral n => n -> n -> [n]
range a b = [a..b]
range' :: Integral n => n -> n -> [n]
range' a b
| a < b = (a : (range' (a+1) b ))
| a == b = [a]
| otherwise = []
-- python enumerate
enumerate :: Integral n => [a] -> [(n,a)]
enumerate = zip [0..]
-- python slice (list[a:b])
slice :: Int -> Int -> [a] -> [a]
slice a b = take (b - a) . drop a
-- insert element at the first point where preticate is True
insertif :: (a -> a -> Bool) -> a -> [a] -> [a]
insertif p i (x:xs)
| p i x = i : x : xs
| otherwise = x : insertif p i xs
insertif _ _ [] = []
-- insert each element, at the first point where the preticate is True, in order
injectif :: (a -> a -> Bool) -> [a] -> [a] -> [a]
injectif p (i:is) (x:xs)
| p i x = i : injectif p is (x:xs)
| otherwise = x : injectif p (i:is) xs
injectif _ [] xs = xs
injectif _ _ [] = []
-- find the list of items that each follow x
next x (i:y:ys) -- take the first two items in the list
| x == i = -- if the first item == x,
y : next x (y:ys) -- take the second, and continue to the rest of the list (minus the first element)
|otherwise = -- not equal,
next x (y:ys) -- so skip that element
next _ [_] = [] -- if there's no second element, then stop
next _ _ = [] -- if the list is empty, stop
-- list intersection which works on infinite lists
isect :: Eq a => [a] -> [a] -> [a]
isect = isectBy (==)
isectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
isectBy eq xs = catMaybes . diagonal . map matches
where matches y = [if eq x y then Just x else Nothing | x <- xs] -- ensures that non-yields are interleaved with yields
--mFilter :: (a -> Bool) -> [a] -> [Maybe a]
--mFilter f xs = [if f x then Just x else Nothing | x <- xs]
--mFilter :: (a -> Bool) -> [a] -> [Maybe a]
--mFilter f (x:xs)
-- | f x = Just x : mFilter f xs
-- | otherwise = Nothing : mFilter f xs
boolMaybe :: (a -> Bool) -> a -> Maybe a
boolMaybe f x
| f x = Just x
| otherwise = Nothing
mFilter :: (a -> Bool) -> [a] -> [Maybe a]
mFilter = map . boolMaybe
-- implementation of fromMaybe, and catMaybes
fromMaybe :: a -> Maybe a -> a
fromMaybe = (`maybe` id)
catMaybes :: (Foldable t, Alternative t) => t (Maybe a) -> t a
catMaybes = foldr
(\x -> case x of
Just x -> (pure x <|>)
Nothing -> id
) empty
-- function to floop a list of maybes into a maybe of a list. yeah, not a great description
floop :: (Foldable t, Alternative t) => t (Maybe a) -> Maybe (t a)
floop xs =
let
f :: (Foldable t, Alternative t) => Maybe a -> Maybe (t a) -> Maybe (t a)
f Nothing = const Nothing
f (Just x) = fmap ((<|>) $ pure x)
--f x ys = maybe Nothing (flip (fmap . (<|>) . pure) ys) x -- is equivalent
in
foldr f (Just empty) xs
-- simpler, more limited example
floop' :: [Maybe a] -> Maybe [a]
floop' [] = Just []
floop' (Nothing:_) = Nothing
floop' (Just x:xs) = fmap (x:) . floop $ xs
--floop' xs = foldr (fmap . (:)) (Just []) xs
--floop'' :: (Foldable t, Alternative t) => t (Maybe a) -> Maybe (t a)
--floop'' xs = foldr (\x ys -> maybe Nothing (flip (fmap . (<|>) . pure) ys) x) (Just empty) xs --needlessly equivalent
-- I finally get this one! -- Source: http://stackoverflow.com/a/41986867/6112457
sequence' :: (Alternative t, Foldable t, Applicative a) => t (a b) -> a (t b)
sequence' = foldr inject (pure empty)
where inject = liftA2 prepend
prepend = (<|>) . pure
-- apply each function with the given argument
applyAll :: [(a -> b)] -> a -> [b]
applyAll fs x = map ($x) fs
main = do
mapM_ print [floop (map Just [1,2,3,4,5]) == Just [1,2,3,4,5]
,floop (Nothing : ( map Just [1,2,3,4,5])) == Nothing
,floop' (map Just [1,2,3,4,5]) == Just [1,2,3,4,5]
,floop' (Nothing : ( map Just [1,2,3,4,5])) == Nothing
,sequence' (map Just [1,2,3,4,5]) == Just [1,2,3,4,5]
,sequence' (Nothing : ( map Just [1,2,3,4,5])) == Nothing
]