Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does newtype help hiding anything?

Tags:

haskell

Real world haskell says:

we will hide the details of our parser type using a newtype declaration

I don't get how we can hide anything using the newtype. Can anyone elaborate? What are we trying to hide and how do we do it.

data ParseState = ParseState {
  string :: L.ByteString
, offset :: Int64           -- imported from Data.Int
} deriving (Show)


newtype Parse a = Parse {
    runParse :: ParseState -> Either String (a, ParseState)
}
like image 772
Trident D'Gao Avatar asked Nov 09 '13 03:11

Trident D'Gao


2 Answers

The idea is to combine modules + newtypes to keep people from seeing the internals of how we implement things.

-- module A
module A (A, toA) where -- Notice we limit our exports
newtype A = A {unA :: Int}

toA :: Int -> A
toA = -- Do clever validation

-- module B
import A
foo :: A
foo = toA 1 -- Must use toA and can't see internals of A

This prevents from pattern matching and arbitrarily constructing A. This let's our A module make certain assumptions about A and also change the internals of A with impunity!

This is particularly nice because at runtime the newtypes are erased so there's almost no overhead from doing something like this

like image 101
Daniel Gratzer Avatar answered Oct 31 '22 16:10

Daniel Gratzer


You hide details by not exporting stuff. So there's two comparisons to make. One is exported vs. not exported:

-- hidden: nothing you can do with "Parse a" values -- though
-- you can name their type
module Foo (Parse) where
newtype Parse a = Parse { superSecret :: a }

-- not hidden: outsiders can observe that a "Parse a" contains
-- exactly an "a", so they can do anything with a "Parse a" that
-- they can do with an "a"
module Foo (Parse(..)) where
newtype Parse a = Parse { superSecret :: a }

The other is more subtle, and is the one RWH is probably trying to highlight, and that is type vs. newtype:

-- hidden, as before
module Foo (Parse) where
newtype Parse a = Parse { superSecret :: a }

-- not hidden: it is readily observable that "Parse a" is identical
-- to "a", and moreover it can't be fixed because there's nothing
-- to hide
module Foo (Parse) where
type Parse a = a
like image 29
Daniel Wagner Avatar answered Oct 31 '22 15:10

Daniel Wagner