简体   繁体   中英

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

I'm a total beginner with Haskell. While trying to solve some practise exercises on hackerrank I stumbled over an error which makes me wonder to do it "the right way"(tm).

What I was trying to do was this:

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 just using Matrix Char instead of Puzzle . But I don't feel that this is an elegant solution. An abstraction into a more specific type feels the right way to go...

Use type not newtype . The former creates a type alias, the latter is a new type declaration. Specifically newtype is kind of special case for data , where the new type represents a "wrapper" over an existing type (which is a case that can be optimized by the compiler).

I think a better solution than the one offered by Jeffrey's answer, at least in the case of more substantial code bases than a toy game, is to keep using newtype but to 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 keep using a truly distinct data type as opposed to resorting to a type alias, which doesn't introduce any new types and will allow completely interchangeable use of Puzzle and Matrix Char with no added type safety (nor expressiveness).

Also, Jeffrey is right in that newtype is more similar to data than typenewtype offers some performance optimisations over data but is more restricted and slightly affects the program evaluation semantics. You're better off reading up on all the various ways of defining types and type aliases in Haskell.

In your case, you might as well substitute data for newtype without changing the behavior of your program; the rest of the program should continue to work identically.

See also: Haskell type vs. newtype with respect to type safety

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM