Skip to content

Instantly share code, notes, and snippets.

@brainrake
Created July 10, 2016 11:56
Show Gist options
  • Save brainrake/b7d47ab15ed3d23562ce59d88ca3b458 to your computer and use it in GitHub Desktop.
Save brainrake/b7d47ab15ed3d23562ce59d88ca3b458 to your computer and use it in GitHub Desktop.
module Main where
import Prelude
import Control.Monad.Eff.Console (log)
-- give a name to an extensible record with fields common to all ducks
type Duck a = { name :: String
, color :: String | a }
-- function that works on all ducks
display :: forall a. Duck a -> String
display duck = duck.name <> " looks " <> duck.color <> "."
-- flight stuff
-- give a name to a thing that has a fly function that takes a duck
type Fly a = ( fly :: forall b. Duck b -> String | a )
-- shortcut to call fly
fly :: forall a. Duck (Fly a) -> String
fly duck = duck.fly duck
-- ways to fly
woosh :: forall a. Duck a -> String
woosh {name} = name <> " flies, woosh!"
wee :: Duck _ -> String
wee {name, color} = name <> " looks " <> color <> " flies, wee!"
-- different stuff to say
quack name = name <> " quacks!"
squeak name = name <> " squeaks!"
-- ducks
mallard :: Duck ( fly :: forall a. Duck a -> String, say :: String )
mallard =
let name = "Mally"
in { name, color: "blue", fly: woosh, say: quack name }
redhead :: Duck (Fly ( say :: String ))
redhead =
let name = "Red"
in { name, color: "red", fly: wee, say: quack name }
rubber :: Duck _
rubber =
let name = "Rube"
in { name, color: "yellow", say: squeak name }
-- tests
main = do
log (fly mallard) --> Mally flies, woosh!
let mallory = mallard { name = "Mallory" }
log (fly mallory) --> Mallory flies, woosh!
log (fly redhead) --> Red looks red and flies, wee!
-- log rubber.fly
-- -- will not compile: rubber can't fly
-- -- in OO, there is no error but nothing happens
log mallard.say --: Mally quacks!
log rubber.say --> Rob squeaks!
log (display mallard) --> Mally looks red.
-- you can extend anything without touching anything else
-- add a way to fly or say
-- add functions common to all ducks
-- add ghost duck with new opacity attribute
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment