case v of _ -> comp
case v of a -> comp
case v of ~pat -> comp
case [] 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 -> comp
Pattern 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)
newtype
Algebraic Datatype Declarations
data D a b = C1 a b
| C2 b b
| C3
Datatype 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
=> 42
case ⊥ of (Cd a) -> 42
=> ⊥
case (Cn ⊥) of (Cn a) -> 42
=> 42
case ⊥ of (Cn a) -> 42
=> 42
wait a sec, how is the last one not a ⊥?
The last way to construct one
case v of N pat -> comp
Pattern N pat
is irrefutable if pat
is.
case ⊥ of (N pat) -> e
=> case ⊥ of pat -> e
case (N v) of (N pat) -> e
=> case v of pat -> e
Monoid
class Monoid a where
mempty :: a
mappend :: a -> a -> a
Which 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 String
trans :: [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'' = coerce
Given
data D = C ...
newtype N = MkN D
and F
is a type-level function,
N
= D
F N
= F D
unsafeCoerce: 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 Functor
newtype Age = MkAge Int deriving Num
newtype Ls a = L [a] deriving Functor
coerce :: 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 a
If 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’