forked from ollef/oslo-haskell
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFoldAndTraverse.hs
More file actions
82 lines (67 loc) · 2.61 KB
/
FoldAndTraverse.hs
File metadata and controls
82 lines (67 loc) · 2.61 KB
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
{-# LANGUAGE DeriveFunctor #-}
-- | Let's fold and traverse some trees
module FoldAndTraverse where
import Control.Monad.State
import Data.Monoid
import Data.Foldable
import Data.Traversable
data Tree a = Leaf a | Fork (Tree a) (Tree a)
deriving (Functor, Show)
instance Foldable Tree where
-- foldMap :: Monoid m => (a -> m) -> Tree a -> m
foldMap f t = todo
exampleTree, exampleTree2 :: Tree Int
exampleTree = Leaf 1 `Fork` ((Leaf 2 `Fork` Leaf 3) `Fork` Leaf 4)
exampleTree2 = Leaf 0 `Fork` (exampleTree `Fork` Leaf 0)
-- | Define the following function in terms of foldMap. Note that it
-- also exists in the Foldable class as 'toList'.
elements :: Tree a -> [a]
elements = todo
test :: [Int]
test = elements exampleTree
instance Traversable Tree where
-- traverse :: Applicative f => (a -> f b) -> Tree a -> f (Tree b)
traverse f t = todo
{- What can we do with traverse?
A useful way of thinking about it is to think of the function (a -> f b) as an
effectful computation. Some examples:
(a -> Maybe b) = A computation that might fail
(a -> [b]) = A non-deterministic (= having many possible answers)
computation
(a -> State s b) = A stateful computation
(a -> (x -> b)) = A computation with a configuration parameter
Thinking of it this way we can try to read the type of the above instantiations
of traverse:
traverse :: (a -> Maybe b) -> Tree a -> Maybe (Tree b)
= apply a possibly failing computation to all the leaves in a tree. If one
of the functions fails, the whole thing fails.
traverse :: (a -> [b]) -> Tree a -> [Tree b]
= apply a non-deterministic computation to all the leaves in a tree.
Return all possible outcomes.
traverse :: (a -> State s b) -> Tree a -> State s (Tree b)
= apply a stateful function to all the leaves in a tree.
traverse :: (a -> (x -> b)) -> Tree a -> x -> Tree b
= apply a function with a configuration to all the leaves in a tree.
-}
maybeTraversals :: (Maybe (Tree Int), Maybe (Tree Int))
maybeTraversals = (traverse (safeDiv 100) exampleTree, traverse (safeDiv 100) exampleTree2)
where
safeDiv _ 0 = Nothing
safeDiv x y = Just (x `div` y)
listTraversal :: [Tree Int]
listTraversal = traverse (\n -> [0..n]) exampleTree
stateTraversal :: (Tree Bool, [Int])
stateTraversal = runState (traverse f exampleTree2) []
where
-- | Add x to the state if it's not already there. Return True if
-- it's a duplicate and False if not.
f :: Int -> State [Int] Bool
f x = do
xs <- get
if x `elem` xs then
return True
else do
put (x:xs)
return False
todo :: a
todo = undefined