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 ...
source to share
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.
source to share