What's the correct way to use type aliases in Haskell

I am new to Haskell. While trying to solve some practical hackerrank exercises, I came across an error that makes me wonder "right" (tm).

What I was trying to do was:

import Data.Matrix

newtype Puzzle = Matrix Char

complete :: Puzzle -> Bool
complete p = '-' `elem` (toList p)

[... more functions using 'Matrix Char']

      

what gave me

Couldn't match expected type ‘Matrix Char’
                with actual type ‘Puzzle’
    In the first argument of ‘toList’, namely ‘p’
    In the second argument of ‘elem’, namely ‘(toList p)’

      

The obvious solution is, of course, to use Matrix Char

instead Puzzle

. But I don't feel like this is an elegant solution. Abstraction into a more concrete type feels the right way ...

+3


source to share


2 answers


Use type

not newtype

. The former creates a type alias, the latter is a new type declaration. In particular, this newtype

is a special case for data

where the new type is a "wrapper" over an existing type (which can be optimized by the compiler).



+7


source


I think a better solution than Jeffrey's suggestion, at least in the case of more substantive code bases than a toy, is to keep using newtype

, but change the code to this:

import Data.Matrix

newtype Puzzle = Puzzle (Matrix Char)

complete :: Puzzle -> Bool
complete (Puzzle matrix) = '-' `elem` toList matrix

      

This will allow you to use a really different datatype rather than using a type alias that does not introduce any new types and will allow for completely interchangeable use Puzzle

and Matrix Char

without adding type safety (or expressiveness).



Also, Jeffrey is correct that it is newtype

more like data

than type

- it newtype

offers some performance optimizations over data

, but is more limited and slightly affects the semantics of program evaluation. You'd better read all the different ways of defining types and types of aliases in Haskell.

In your case, you can replace data

with newtype

without changing the behavior of your program; the rest of the program should continue to work the same way.

See also: Haskell type versus newtype regarding type safety

+3


source







All Articles