Skip to content

Instantly share code, notes, and snippets.

@hyperrealgopher
Created March 27, 2021 07:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyperrealgopher/dd7332b6bd08dfce4b284d28ab5addc4 to your computer and use it in GitHub Desktop.
Save hyperrealgopher/dd7332b6bd08dfce4b284d28ab5addc4 to your computer and use it in GitHub Desktop.
system-f/fp-course: Functor.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE InstanceSigs #-}
module Course.Functor where
import Course.Core
import Course.ExactlyOne
import Course.Optional
import Course.List
import qualified Prelude as P(fmap)
-- | All instances of the `Functor` type-class must satisfy two laws. These laws
-- are not checked by the compiler. These laws are given as:
--
-- * The law of identity
-- `∀x. (id <$> x) ≅ x`
--
-- * The law of composition
-- `∀f g x.(f . g <$> x) ≅ (f <$> (g <$> x))`
class Functor k where
-- Pronounced, eff-map.
(<$>) ::
(a -> b)
-> k a
-> k b
infixl 4 <$>
-- $setup
-- >>> :set -XOverloadedStrings
-- >>> import Course.Core
-- >>> import qualified Prelude as P(return, (>>))
-- | Maps a function on the ExactlyOne functor.
--
-- >>> (+1) <$> ExactlyOne 2
-- ExactlyOne 3
instance Functor ExactlyOne where
(<$>) ::
(a -> b)
-> ExactlyOne a
-> ExactlyOne b
f <$> (ExactlyOne a) = ExactlyOne (f a)
-- | Maps a function on the List functor.
--
-- >>> (+1) <$> Nil
-- []
--
-- >>> (+1) <$> (1 :. 2 :. 3 :. Nil)
-- [2,3,4]
instance Functor List where
(<$>) ::
(a -> b)
-> List a
-> List b
f <$> ls = map' f Nil ls
where
map' f acc (e :. es) = map' f (f e :. acc) es
map' f acc Nil = reverse acc
-- | Maps a function on the Optional functor.
--
-- >>> (+1) <$> Empty
-- Empty
--
-- >>> (+1) <$> Full 2
-- Full 3
instance Functor Optional where
(<$>) ::
(a -> b)
-> Optional a
-> Optional b
f <$> (Full a) = Full (f a)
_ <$> Empty = Empty
-- | Maps a function on the reader ((->) t) functor.
--
-- >>> ((+1) <$> (*2)) 8
-- 17
instance Functor ((->) t) where
(<$>) ::
(a -> b)
-> ((->) t a)
-> ((->) t b)
f1 <$> f2 = f1 . f2
-- | Anonymous map. Maps a constant value on a functor.
--
-- >>> 7 <$ (1 :. 2 :. 3 :. Nil)
-- [7,7,7]
--
-- prop> \x a b c -> x <$ (a :. b :. c :. Nil) == (x :. x :. x :. Nil)
--
-- prop> \x q -> x <$ Full q == Full x
(<$) ::
Functor k =>
a
-> k b
-> k a
c <$ ls = const c <$> ls
-- | Anonymous map producing unit value.
--
-- >>> void (1 :. 2 :. 3 :. Nil)
-- [(),(),()]
--
-- >>> void (Full 7)
-- Full ()
--
-- >>> void Empty
-- Empty
--
-- >>> void (+10) 5
-- ()
void ::
Functor k =>
k a
-> k ()
void k = (const ()) <$> k
-----------------------
-- SUPPORT LIBRARIES --
-----------------------
-- | Maps a function on an IO program.
--
-- >>> reverse <$> (putStr "hi" P.>> P.return ("abc" :: List Char))
-- hi"cba"
instance Functor IO where
(<$>) =
P.fmap
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment