


case v of _ -> compcase v of a -> compcase v of ~pat -> compcase [] of {(x:xs) -> 42}Error: Non-exhaustive patterns in case
case [] of {~(x:xs) -> 42}Value: 42
case [] of {~(x:xs) -> x}Error: Irrefutable pattern failed for pattern (x : xs)
case v of a@pat -> compPattern a@pat is irrefutable if pat is.
case [] of {a@ (x:xs) -> a}Error: Non-exhaustive patterns in case
case [] of {a@ ~(x:xs) -> a}Value: []
case [] of {a@ ~(x:xs) -> x}Error: Irrefutable pattern failed for pattern (x : xs)
newtypeAlgebraic Datatype Declarations
data D a b = C1 a b
| C2 b b
| C3Datatype Renamings
newtype N0 = Cn0 Bool
newtype N1 a = Cn1 [Int]Given a data structure
data D = C0 | C1 | C2 | C3
using data..
data W = Cd D
using newtype..
newtype N = Cn D
newtype constructor is unlifted
case (Cd ⊥) of (Cd a) -> 42
=> 42case ⊥ of (Cd a) -> 42
=> ⊥case (Cn ⊥) of (Cn a) -> 42
=> 42case ⊥ of (Cn a) -> 42
=> 42wait a sec, how is the last one not a ⊥?
The last way to construct one
case v of N pat -> compPattern N pat is irrefutable if pat is.
case ⊥ of (N pat) -> e
=> case ⊥ of pat -> ecase (N v) of (N pat) -> e
=> case v of pat -> eMonoid
class Monoid a where
mempty :: a
mappend :: a -> a -> aWhich definition of mappend we want?
and, or, xor, .. ?
newtype All = All { getAll :: Bool }
instance Monoid All where
mempty = All True
All x `mappend` All y = All (x && y)newtype Any = Any { getAny :: Bool }
instance Monoid Any where
mempty = Any False
Any x `mappend` Any y = Any (x || y)Given
newtype HTML = MkHTML Stringtrans :: [HTML] -> [String]
deriving
Slow!
trans :: [HTML] -> [String]
trans [] = []
trans (MkHTML s:xs) = x:(trans xs)
unsafeCoerce :: a -> b coerce :: Coercible * a b =>
a -> b Fast!
trans' :: [HTML] -> [String]
trans' = unsafeCoerce
trans'' :: [HTML] -> [String]
trans'' = coerceGiven
data D = C ...
newtype N = MkN Dand F is a type-level function,
N = DF N = F DunsafeCoerce: force F N = F D
coerce: Coercible (F N) (F D) then F N = F D
how do we (or GHC) know (F N) and (F D)
are coercible?
Sure we can
deriving ( Eq
, Ord
, Read
, Show
, Bounded
, Generic)Is this ok?
deriving Functornewtype Age = MkAge Int deriving Num
newtype Ls a = L [a] deriving Functorcoerce :: Coercible * a b =>
a -> b how do we (or GHC) know (F N) and (F D)
are coercible?
Having roles assigned to type variables of datatypes, classes, and type synonyms.
This a has role phantom
data Phant a = MkPhant Bool For any t1 and t2, GHC automatically has
instance Coercible (Phant t1) (Phant t2)This a has role representational
data Simple a = MkSimple aIf t1 representationally equals to and t2, then
instance Coercible (Simple t1) (Simple t2)This a has role nominal
data Complex a = MkComplex (F a)If
F t1 = u1,F t2 = u2,u1 = u2 (identical); theninstance Coercible (Complex t1) (Complex t2)newtype Age = MkAge Int
type role Cr representational
data Cr a = MkCr a
type role Cn nominal
data Cn a = MkCn a (coerce :: Cr Age -> Cr Int) (MkCr $ MkAge 1)
=> MkCr 1
(coerce :: Cn Age -> Cn Int) (MkCn $ MkAge 1)
=> Couldn't match type ‘Age’ with ‘Int’