在Haskell中使用类型别名的正确方法是什么

时间:2015-08-04 21:28:52

标签: haskell

我是Haskell的初学者。在尝试解决关于hackerrank的一些练习练习时,我偶然发现了一个错误,这让我想知道这样做了#34;正确的方式"(tm)。

我试图做的是:

import Data.Matrix

newtype Puzzle = Matrix Char

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

[... more functions using 'Matrix Char']
是什么给了我

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)’

显而易见的解决方案当然只是使用Matrix Char而不是Puzzle。但我不觉得这是一个优雅的解决方案。抽象为更具体的类型感觉是正确的方式......

2 个答案:

答案 0 :(得分:7)

使用type而不是newtype。前者创建一个类型别名,后者是一个新类型声明。具体来说,newtypedata的一种特殊情况,其中新类型表示"包装"在现有类型上(这是可以由编译器优化的情况)。

答案 1 :(得分:3)

我认为比Jeffrey的答案提供的更好的解决方案,至少在比玩具游戏更具实质性的代码基础的情况下,是继续使用newtype但是要将代码更改为这样:

import Data.Matrix

newtype Puzzle = Puzzle (Matrix Char)

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

这将允许您继续使用真正独特的数据类型,而不是诉诸类型别名,它不会引入任何新类型,并允许完全互换使用Puzzle和{{1没有增加类型安全性(也没有表现力)。

此外,Jeffrey的正确观点是Matrix Charnewtype更相似而不是data - type提供了一些优于newtype的效果优化,但更受限制并略微影响程序评估语义。您最好阅读有关在Haskell中定义类型和类型别名的各种方法。

在您的情况下,您也可以在不更改程序行为的情况下将data替换为data;程序的其余部分应继续以相同的方式工作。

另请参阅:Haskell type vs. newtype with respect to type safety