summaryrefslogtreecommitdiff
path: root/Haskell-book/21/instances/src/Tree.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Haskell-book/21/instances/src/Tree.hs')
-rw-r--r--Haskell-book/21/instances/src/Tree.hs44
1 files changed, 44 insertions, 0 deletions
diff --git a/Haskell-book/21/instances/src/Tree.hs b/Haskell-book/21/instances/src/Tree.hs
new file mode 100644
index 0000000..5c0740c
--- /dev/null
+++ b/Haskell-book/21/instances/src/Tree.hs
@@ -0,0 +1,44 @@
+module Tree where
+
+import Data.Monoid
+import Test.QuickCheck
+import Test.QuickCheck.Checkers
+import Test.QuickCheck.Classes
+
+-- Solution:
+-- https://www.reddit.com/r/HaskellBook/comments/7w7bqn/ch_21_is_this_a_sane_instance_of_traversable/
+
+data Tree a = Empty
+ | Leaf a
+ | Node (Tree a) a (Tree a)
+ deriving (Eq, Show)
+
+instance Functor Tree where
+ fmap _ Empty = Empty
+ fmap f (Leaf x) = Leaf $ f x
+ fmap f (Node x y z) = Node (fmap f x) (f y) (fmap f z)
+
+-- foldMap is a bit easier and looks more natural, but you can do
+-- foldr too for extra credit.
+instance Foldable Tree where
+ foldMap _ Empty = mempty
+ foldMap f (Leaf x) = f x
+ foldMap f (Node x y z) = (foldMap f x) <> (f y) <> (foldMap f z)
+
+instance Traversable Tree where
+ traverse f Empty = pure Empty
+ traverse f (Leaf x) = Leaf <$> f x
+ traverse f (Node x y z) = Node <$> (traverse f x) <*> (f y) <*> (traverse f z)
+
+instance Arbitrary a => Arbitrary (Tree a) where
+ arbitrary = do
+ x <- arbitrary
+ y <- arbitrary
+ z <- arbitrary
+ frequency [ (1, return Empty)
+ , (2, return $ Leaf y)
+ , (3, return $ Node x y z)
+ ]
+
+instance Eq a => EqProp (Tree a) where
+ (=-=) = eq