Newtype
From HaskellWiki
(Difference between revisions)
(basically rewrote it) |
m (italics are better than bold here) |
||
| Line 1: | Line 1: | ||
| - | A <hask>newtype</hask> declaration creates a new type in much the same way as <hask>data</hask>. The syntax and usage of newtypes is virtually identical to that of data declarations - in fact, you can replace the <hask>newtype</hask> keyword with <hask>data</hask> and it'll still compile, indeed there's even a good chance your program will still work. The converse is not true, however - <hask>data</hask> can only be replaced with <hask>newtype</hask> if the type has | + | A <hask>newtype</hask> declaration creates a new type in much the same way as <hask>data</hask>. The syntax and usage of newtypes is virtually identical to that of data declarations - in fact, you can replace the <hask>newtype</hask> keyword with <hask>data</hask> and it'll still compile, indeed there's even a good chance your program will still work. The converse is not true, however - <hask>data</hask> can only be replaced with <hask>newtype</hask> if the type has ''exactly one constructor'' with ''exactly one field'' inside it. |
Some examples: | Some examples: | ||
Revision as of 11:42, 24 October 2010
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 -> (s, a)) -> State s a runState :: State s a -> (s -> (s, a))
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.
