Phil Schumann, Berlin
 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
There are two ways of constructing a software design: one way is to make it so simple that there are obviously no deficiencies, and the other way is make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
Tony Hoare
Sourcery
Working with since • 1998 » BasicPascal1999 » HTMLASP2000 » SQLCSSJSVB2001 » JavaPHP2002 » C#ASP.NET2003 » XSLT / XPath2004 » Prolog2006 » SharePoint2008 » F# • Python • Lisp2011 » Go • WebGL • Node.js • CoffeeScript • 2012 » OpenGLGLSL2015 » Haskell2016 » TypeScriptElm2017 » PureScriptVue.js
Details..
Making-of
Site theme: none; hand-crafted.
Static site gen: HaXtatic.
Icons, logos, fonts: © respective owners.