Skip to content

Instantly share code, notes, and snippets.

@raichoo
Last active August 29, 2015 14:22
Show Gist options
  • Save raichoo/8a94fbc706501a4e7864 to your computer and use it in GitHub Desktop.
Save raichoo/8a94fbc706501a4e7864 to your computer and use it in GitHub Desktop.
Preventing GND from doing nasty stuff
-- This MinList example is taken from the Safe Haskell paper
{-# LANGUAGE Safe #-}
{-# LANGUAGE RoleAnnotations #-}
module MinList (MinList, newMinList, insertMin) where
data MinList a = MinList a [a]
deriving Show
type role MinList nominal
-- invariant: only insert values that are larger than `m`
insertMin :: Ord a => a -> MinList a -> MinList a
insertMin x l@(MinList m xs)
| x > m = MinList m (x:xs)
| otherwise = l
newMinList :: a -> MinList a
newMinList m = MinList m []
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Main where
import Control.Applicative
import MinList
class IntIso t where
iso :: MinList t -> MinList Int
instance IntIso Int where
iso = id
-- won't compile Int and I are not nominally equal
newtype I = I Int deriving (Eq, IntIso)
instance Ord I where
compare (I x) (I y) = compare y x
nums = [1,4,0,1,-5,2,3]
goodList :: Maybe (MinList Int)
goodList = case nums of
x:xs -> Just $ foldl (flip insertMin) (newMinList x) xs
_ -> Nothing
-- Will produce a `MinList Int` which violated MinList invariants
badList :: Maybe (MinList Int)
badList = iso <$> case nums of
x:xs -> Just $ foldl (flip insertMin) (newMinList (I x)) (map I xs)
_ -> Nothing
main :: IO ()
main = do
print goodList
print badList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment