Home > OS >  newtypes in Haskell with more than one arguments
newtypes in Haskell with more than one arguments

Time:11-14

In Haskell I try to call the following two newtypes that have I have declared.

Why does this work:

newtype CharList = CharList { get2CharList :: [Char] } deriving (Eq, Show)   

ghci> CharList "some"    
CharList {get2CharList = "some"}

When this does not work:

newtype Pair a b = Pair { createPair :: (a, b) } deriving (Eq, Show)

ghci> Pair 2 4
<interactive>:13:1: error:
    * Couldn't match expected type: t0 -> t
                  with actual type: Pair a0 b0
    * The function `Pair' is applied to two value arguments,
        but its type `(a0, b0) -> Pair a0 b0' has only one
      In the expression: Pair 2 4
      In an equation for `it': it = Pair 2 4
    * Relevant bindings include it :: t (bound at <interactive>:13:1)

Does it require a Monad to work as seen here: The Writer monad and its type declaration And will I necessarily then have to constraint the type when calling the newtype

Furthermore, how can I go about it if I want a newtype to take even more arguments such as 3?

CodePudding user response:

The Pair newtype is declared as containing (or wrapping) a tuple of values, so that's what you must supply to create a value:

ghci> Pair (2, 4)
Pair {createPair = (2,4)}

You can extract the tuple from a Pair value with createPair:

ghci> createPair $ Pair (2, 4)
(2,4)

While the type is given as Pair a b (without brackets or comma), the data constructor requires a tuple. The type is declared to the left of the equal sign, and the data constructor is to the right.

The syntax Pair (2, 4) is just shorthand for the full data constructor, which is also possible:

ghci> Pair { createPair = (2, 4) }
Pair {createPair = (2,4)}

You can create wrappers with more type arguments in the same way:

newtype Triple a b c = T { getTriple :: (a, b, c) } deriving (Eq, Show)

This example also showcases something that may help understanding the above. The name of the type doesn't have to be the same as the name of the data constructor. Here, the name of the type is Triple, while the name of the data constructor is T.

You create a value of Triple using the data constructor T:

ghci> T (1, "foo", True)
T {getTriple = (1,"foo",True)}

The type of that expression is:

ghci> :t T (1, "foo", True)
T (1, "foo", True) :: Num a => Triple a String Bool
  • Related