Phil Schumann, Germany
 Software Developer

05 Feb 2017 For the "begintermediate" Funk(y-nota)tional Programmer, until more auto-math-ic intuition sets in, a quick-lookup cheat-sheet: examples of the built-in common standard instances for these two foundational Haskell typeclasses (for when GHCi isn't at hand, which it should never be).

HasPlained: Functor & Applicative

For the "begintermediate" Funk(y-nota)tional Programmer, until more auto-math-ic intuition sets in, a quick-lookup cheat-sheet: examples of the built-in common standard instances for these two foundational Haskell typeclasses (for when GHCi isn't at hand, which it should never be).

Functor — <$> , <$

A Functor, to "get mapped over", declares fmap :: (a→b) → (f a) → (f b) aka. <$> (this flipped being >~ in my code-bases) with laws:

  • id <$> fooid foo
  • ((f <$>).(g <$>)) foof.g <$> foo
  • baz <$ foo(const baz) <$> foo

Applicative — pure , <*> , <* , *>

An Applicative (also always a Functor) "declares a functor with extra laws and operations to enable more/structured functorial computations". Meaning approximately,

  • pure brings a value a into the functor f as f a, and
  • <*> allows applying some function-in-the-functor f (a->b) (often a partial application obtained from an earlier <$>) to such a value-in-the-functor f a to obtain the returned such value-in-the-functor f b.
  • <**> it not a flip of <*> but of some deeper inner $, ie. "convoluted ×2"
  • *> discards left-hand side result, <* same for right-hand but only because:
  • (<* func_in_functor) is not a flip of *> but of the original function encapsulated by func_in_functor!

All a tad too knotty for my taste, but the basics still need to be understood for comprehending Haskell code-bases. As for the laws.. similarly labyrinthine, mostly needed when writing instances (such as on top of a custom Functor) or for reasoning about existing Applicative-style code.

Maybe

Given dis = Nothing and dat = Just "foo"

Functor — <$> , <$

  • dis>~reversereverse<$> disfmap reverse disNothing
  • dat>~reversereverse<$> datfmap reverse datJust "oof"
  • "baz" <$ disNothing
  • "baz" <$ datJust "baz"

Applicative — pure , <*> , <* , *>

Further also given cmp = compare <$> dem where dem = (pure "bar") :: Maybe Stringdem = Just "bar"

  • cmp <*> dis ≡ (here) dis <**> cmpNothing
  • cmp <*> dat ≡ (here) dat <**> cmpJust LT
  • cmp *> disdis <* cmpNothing
  • cmp *> datdat <* cmpJust "foo"
  • Just 10 <* Just "20"Just 10
  • Just 10 *> Just "20"Just "20"
  • Just _ *> NothingNothing *> Just _Just _ <* NothingNothing <* Just _Nothing

Either t

Given dis = Left "baz" and dat = Right "foo"

Functor — <$> , <$

  • dis>~reversereverse<$> disfmap reverse disLeft "baz"
  • dat>~reversereverse<$> datfmap reverse datRight "oof"
  • "bar" <$ disLeft "baz"
  • "bar" <$ datRight "bar"

Applicative — pure , <*> , <* , *>

Further also given cmp = compare <$> dem where dem = (pure "bar") :: Either String Stringdem = Right "bar"

  • cmp <*> dis ≡ (here) dis <**> cmpLeft "baz"
  • cmp <*> dat ≡ (here) dat <**> cmpRight LT
  • cmp *> disdis <* cmpLeft "baz"
  • cmp *> datdat <* cmpRight "foo"
  • Right 10 <* Right "20"Right 10
  • Right 10 *> Right "20"Right "20"
  • Left anything *> __ *> Left anythingLeft anything <* __ <* Left anythingLeft anything

(t,)

Given disndat = ("baz","foo")

Functor — <$> , <$

  • disndat>~reversereverse<$> disndatfmap reverse disndat("baz","oof")
  • "bar" <$ disndat("baz","bar")

Applicative — pure , <*> , <* , *>

Further also given cmp = compare <$> dem where dem = (pure "bar") :: (String,String)dem = ("","bar")

  • cmp <*> disndat ≡ (here) disndat <**> cmp("baz",LT)
  • cmp *> disndatdisndat <* cmp("baz","foo")
  • ("a",'b') <* ("c",'d')("ac",'b')
  • ("a",'b') *> ("c",'d')("ac",'d')
  • (GT,True) <* (LT,False)(GT,True)
  • (GT,True) *> (LT,False)(GT,False)

[]

Given dis = [] and dat = ["foo","baz"]

Functor — <$> , <$

  • dis>~reversereverse<$> disfmap reverse dis[]
  • dat>~reversereverse<$> datfmap reverse dat["oof","zab"]
  • "bar" <$ dis[]
  • "bar" <$ dat["bar","bar"]

Applicative — pure , <*> , <* , *>

Further also given cmp = compare <$> dem where dem = (pure "dem") :: [String]dem = ["dem"]

  • cmp <*> dis ≡ (here) dis <**> cmp[]
  • cmp <*> dat ≡ (here) dat <**> cmp[LT,GT]
  • cmp *> disdis <* cmp[]
  • cmp *> datdat <* cmp["foo","baz"]
  • [1,2] <* [3,4][1,1,2,2]
  • [1,2] <* [3,4,5][1,1,1,2,2,2]
  • [1,2] <* [3,4,5,6][1,1,1,1,2,2,2,2]
  • [1,2,3,4] *> [5,6][5,6,5,6,5,6,5,6]
  • "yo" *> "foo""foofoo"
  • "yo" <* "fee""yyyooo"
  • "zoom" *> "ya""yayayaya"
  • "zoom" <* "ya""zzoooomm"
  • [] *> __ *> [][] <* __ <* [][]
  • [reverse , id] <*> ["foo","bar"]["oof","rab","foo","bar"]

IO

Given dat = (pure "foo") :: IO String

Functor — <$> , <$

  • dat>~reversereverse<$> datfmap reverse datdat >>= (pure . reverse)(pure "oof") :: IO String
  • "baz" <$ dat(pure "baz") :: IO String

Applicative — pure , <*> , <* , *>

Further also given dis = (pure "") :: IO String and cmp = compare <$> dem where dem = (pure "dem") :: IO String

  • cmp <*> dis ≡ (here) dis <**> cmp(pure GT) :: IO Ordering
  • cmp <*> dat ≡ (here) dat <**> cmp(pure LT) :: IO Ordering
  • cmp *> disdis <* cmp(pure "") :: IO String
  • cmp *> datdat <* cmp(pure "foo") :: IO String
  • dis *> datdat <* dis(pure "foo") :: IO String
  • dat *> disdis <* dat(pure "") :: IO String

t ->

Given dat = "foo-bar" and dis = [1,2,3,4] or [] or [True] or any other list..

Functor — <$> , <$

  • (tail>~reverse) dat(reverse <$> tail) dat(fmap reverse tail) dat(reverse . tail) dat(tail~.reverse) dat"rab-oo"
  • (reverse>~tail) dat(tail <$> reverse) dat(fmap tail reverse) dat(tail . reverse) dat(reverse~.tail) dat"ab-oof"
  • (reverse>~head) dat(head <$> reverse) dat(fmap head reverse) dat(head . reverse) dat(reverse~.head) dat'r'
  • (tail <$ head) dis dattail dat"oo-bar"
  • (head <$ tail) dis dathead dat'f'

Applicative — pure , <*> , <* , *>

Really not ready to go there..

 
Cogent
Everything is vague to a degree you do not realize till you have tried to make it precise.
Bertrand Russell
Sourcery
Working with since1998 » BasicPascal1999 » HTMLASP2000 » SQLCSSJSVB2001 » JavaPHP2002 » C#ASP.NET2003 » XSLT / XPath2004 » Prolog2006 » SharePoint2008 » F# • Python • Lisp2011 » Go • WebGL • Node.js • CoffeeScript • 2012 » OpenGLGLSL2015 » Haskell2016 » TypeScriptElm2017 » PureScriptVue.jsGraphQL2018 » Lua
Details..
Making-of
Site theme: none; hand-crafted.
Static site gen: HaXtatic.
Icons, logos, fonts: © respective owners.