# Newtype

### From HaskellWiki

(Difference between revisions)

m (... and in the type of runState) |
m (Fixed spelling.) |
||

Line 37: | Line 37: | ||

== The messy bits == |
== The messy bits == |
||

− | Why doesn't everyone just use <hask>newtype</hask> whenever they can, then? Well, quite often they do. But there is a subtle yet sematically significant difference. When we create a data type supposedly isomorphic to <hask>Bool</hask> like so: |
+ | Why doesn't everyone just use <hask>newtype</hask> whenever they can, then? Well, quite often they do. But there is a subtle yet semantically significant difference. When we create a data type supposedly isomorphic to <hask>Bool</hask> like so: |

<haskell>data Any = Any { getAny :: Bool }</haskell> |
<haskell>data Any = Any { getAny :: Bool }</haskell> |

## Latest revision as of 18:32, 30 September 2012

Anewtype

data

newtype

data

data

newtype

*exactly one constructor*with

*exactly one field*inside it.

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 |

## [edit] 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))

*isomorphic*. This means that after the type is checked at compile time, at run time the two types can be treated essentially the same, without the overhead or indirection normally associated with a data constructor. So if you want to declare different type class instances for a particular type, or want to make a type abstract, you can wrap it in a

newtype

## [edit] 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

*lifted*- that is, they contain their own ⊥ value that is distinct from all the others. In this example, we have

⊥ :: Any

Any ⊥ :: Any

case x of Any _ -> ()

x

⊥

Any y

y

newtype

## [edit] 3 What about strict types?

You may notice that a type like

data Identity' a = Identity' !a

Identity' ⊥ = ⊥

Identity' ⊥

Identity' $! ⊥

## [edit] 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

## [edit] 5 See also

The Haskell 98 Report defines newtypes in section 4.2.3.