Newtype
From HaskellWiki
Anewtype
data
newtype
data
data
newtype
Some examples:
newtype Fd = Fd CInt -- data Fd = Fd CInt would also be valid -- newtypes can have deriving clauses just like normal types newtype Identity a = Identity a deriving (Eq, Ord, Read, Show) -- record syntax is still allowed, but only for one field newtype State s a = State { runState :: s -> (s, a) } -- this is *not* allowed: -- newtype Pair a b = Pair { pairFst :: a, pairSnd :: b } -- but this is: data Pair a b = Pair { pairFst :: a, pairSnd :: b } -- and so is this: newtype Pair' a b = Pair' (a, b)
newtype
Contents |
1 The short version
The restriction to one constructor with one field means that the new type and the type of the field are in direct correspondence:
State :: (s -> (a, s)) -> State s a runState :: State s a -> (s -> (a, s))
newtype
2 The messy bits
Why doesn't everyone just usenewtype
Bool
data Any = Any { getAny :: Bool }
we actually find that the isomorphism isn't exact:
Any . getAny $ Any True = Any True -- okay, fine Any . getAny $ Any False = Any False -- also fine Any . getAny $ Any ⊥ = Any ⊥ -- so far so good Any . getAny $ ⊥ = Any ⊥ -- wait a second...
(what's that upside-down T thing?)
The problem is that types declared with thedata
⊥ :: Any
Any ⊥ :: Any
case x of Any _ -> ()
x
⊥
Any y
y
newtype
3 What about strict types?
You may notice that a type like
data Identity' a = Identity' !a
Identity' ⊥ = ⊥
Identity' ⊥
Identity' $! ⊥
4 Examples
module Foo where data Foo1 = Foo1 Int -- Defines Foo1 constructor that lazily refers to an Int data Foo2 = Foo2 !Int -- Defines Foo2 constructor that strictly refers to an Int newtype Foo3 = Foo3 Int -- Defines Foo3 constructor that is synonymous with Int -- Argument is lazy and ignored, so -- undefined does not cause failure since -- the contructor pattern match succeeds. x1 = case Foo1 undefined of Foo1 _ -> 1 -- 1 -- Argument is strict (because of !), so -- undefined does cause failure. x2 = case Foo2 undefined of Foo2 _ -> 1 -- undefined -- The newtype behaves like Int, see yInt below x3 = case Foo3 undefined of Foo3 _ -> 1 -- 1 -- Constructor pattern match fails y1 = case undefined of Foo1 _ -> 1 -- undefined -- Constructor pattern match fails y2 = case undefined of Foo2 _ -> 1 -- undefined -- The newtype behaves like Int, there is no -- constructor at runtime. y3 = case undefined of Foo3 _ -> 1 -- 1 -- Demonstration of Int behavior int :: Int int = undefined yInt = case int of _ -> 1 -- 1
5 See also
The Haskell 98 Report defines newtypes in section 4.2.3.
