diff --git a/20-foldable/20.5-library-functions.md b/20-foldable/20.5-library-functions.md index bdab0f8..4f57bdf 100644 --- a/20-foldable/20.5-library-functions.md +++ b/20-foldable/20.5-library-functions.md @@ -1,2 +1,19 @@ -# Exercises: Library Functions +# 20.5 Some basic derived operations + +Why does `fmap length Just [1, 2, 3]` return 1? + +```haskell +fmap :: Functor f => (a -> b) -> f a -> f b +length :: Foldable t => t a -> Int +Just :: a -> Maybe a + +fmap length :: (Foldable t, Functor f) => f (t a) -> f Int +-- notice that the next argument given is an f (t a) and since +-- (->) is also a functor f is ((->) a) and (t a) is Maybe a +-- this also makes f Int an (a -> Int) +fmap length Just :: a -> Int +``` + +## Exercises: Library Functions + see src/functions.h \ No newline at end of file diff --git a/20-foldable/src/chapter.hs b/20-foldable/src/chapter.hs index f7fa60c..87704a4 100644 --- a/20-foldable/src/chapter.hs +++ b/20-foldable/src/chapter.hs @@ -10,7 +10,7 @@ data Constant a b = Constant b deriving (Eq, Show) instance Foldable (Constant a) where foldr f z (Constant b) = f b z foldMap f (Constant b) = f b --- 1' Mistake in book, probably meant: +-- 1' Mistake in book as (1) is just Identity with shadow a, probably meant: data Constant' a b = Constant' a deriving (Eq, Show) instance Foldable (Constant' a) where foldr _ z _ = z @@ -47,4 +47,4 @@ filterF f = foldr (\a b -> if f a then pure a `mappend` b else b) mempty filterF' :: (Applicative f, Foldable t, Monoid (f a)) => (a -> Bool) -> t a -> f a -filterF' f = foldMap (\a -> if f a then pure a else mempty) \ No newline at end of file +filterF' f = foldMap (\a -> if f a then pure a else mempty) \ No newline at end of file diff --git a/20-foldable/src/functions.hs b/20-foldable/src/functions.hs index 04e3ab5..5130420 100644 --- a/20-foldable/src/functions.hs +++ b/20-foldable/src/functions.hs @@ -1,6 +1,7 @@ module Functions where import Data.Monoid +import Data.Maybe -- foldMap :: (Monoid m, Foldable t) => (a -> m) -> t a -> m -- foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b @@ -18,11 +19,21 @@ elem' :: (Foldable t, Eq a) => a -> t a -> Bool elem' e = getAny . (foldMap (Any . (==e))) minimum' :: (Foldable t, Ord a) => t a -> Maybe a -minimum' = foldr (\a b -> +minimum' = foldr (\a b -> case b of Nothing -> Just a Just a' -> Just $ min a a') Nothing +-- -- In order to use foldMap we need a monoid instance for smallest value +-- data Smallest a = Smallest { getSmallest :: Maybe a } +-- instance Ord a => Monoid (Smallest a) where +-- mempty = Smallest Nothing +-- mappend (Smallest Nothing) m = m +-- mappend m (Smallest Nothing) = m +-- mappend (Smallest (Just a1)) (Smallest (Just a2)) = +-- Smallest $ Just (min a1 a2) +-- minimum' = getSmallest . foldMap (Smallest . Just) + maximum' :: (Foldable t, Ord a) => t a -> Maybe a maximum' = foldr (\a b -> @@ -30,20 +41,35 @@ maximum' = foldr (\a b -> Nothing -> Just a Just a' -> Just $ max a a') Nothing +-- In order to use foldMap we need a monoid instance for largest value +-- data Largest a = Largest { getLargest :: Maybe a } +-- instance Ord a => Monoid (Largest a) where +-- mempty = Largest Nothing +-- mappend (Largest Nothing) m = m +-- mappend m (Largest Nothing) = m +-- mappend (Largest (Just a1)) (Largest (Just a2)) = +-- Largest $ Just (max a1 a2) +-- maximum' = getLargest . foldMap (Largest . Just) + null' :: Foldable t => t a -> Bool null' = foldr (\_ _ -> False) True +-- Not very pretty, but it works: +-- null' = isNothing . getFirst . foldMap (First . Just) length' :: Foldable t => t a -> Int length' = foldr (\_ b -> b + 1) 0 +-- length' = getSum . foldMap (Sum . const 1) toList' :: Foldable t => t a -> [a] toList' = foldr (:) [] +-- toList' = foldMap (:[]) fold' :: (Foldable t, Monoid m) => t m -> m -- fold' = foldMap (mappend mempty) -- mappend mempty = id fold' = foldMap id +-- fold' = foldr mappend mempty foldMap' :: (Foldable t, Monoid m) => (a -> m) -> t a -> m -- foldMap' f = foldr (\a b -> mappend (f a) b) mempty -foldMap' f = foldr (mappend . f) mempty \ No newline at end of file +foldMap' f = foldr (mappend . f) mempty