Skip to content

Instantly share code, notes, and snippets.

@markhibberd
Created October 14, 2014 03:09
Show Gist options
  • Save markhibberd/51938ab9841224778d5c to your computer and use it in GitHub Desktop.
Save markhibberd/51938ab9841224778d5c to your computer and use it in GitHub Desktop.
{-# LANGUAGE GADTs #-}
{-# LANGUAGE Rank2Types #-}
{-
Lets start ^^ by enabling some language extensions. GADTs to encode our data types and
Rank2Types for the existental we will need to hide our types when we don't care about
the invariant.
-}
{-
Lets start with our key data type, we want to be able to represent
keys that point to a String, an Int or a Bool.
-}
data Key a where
S :: String -> Key String
I :: String -> Key Int
B :: String -> Key Bool
{-
Lets than create an "entry in a bag" that holds any well typed
key-value pair. Note well that we explicitly want to hide the
invariants that our keys maintain at this point.
-}
data Entry =
forall a. Entry (Key a) a
{-
A simple representation of a Bag as a list of entries.
-}
type Bag =
[Entry]
flag :: Key Bool
flag = B "flag"
counter :: Key Int
counter = I "flag"
name :: Key String
name = S "name"
stuff :: Bag
stuff = [
Entry flag True
, Entry counter 0
, Entry name "mth"
]
get :: Key a -> Bag -> Maybe a
get a [] =
Nothing
get a ((Entry k v) : xs) =
let next = get a xs
in case (k, a) of
(S s, S s') -> if s == s' then Just v else next
(I i, I i') -> if i == i' then Just v else next
(B i, B i') -> if i == i' then Just v else next
_ -> next
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment