Created
October 14, 2014 03:09
-
-
Save markhibberd/51938ab9841224778d5c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# 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