我是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
。但我不觉得这是一个优雅的解决方案。抽象为更具体的类型感觉是正确的方式......
答案 0 :(得分:7)
使用type
而不是newtype
。前者创建一个类型别名,后者是一个新类型声明。具体来说,newtype
是data
的一种特殊情况,其中新类型表示"包装"在现有类型上(这是可以由编译器优化的情况)。
答案 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 Char
与newtype
更相似而不是data
- type
提供了一些优于newtype
的效果优化,但更受限制并略微影响程序评估语义。您最好阅读有关在Haskell中定义类型和类型别名的各种方法。
在您的情况下,您也可以在不更改程序行为的情况下将data
替换为data
;程序的其余部分应继续以相同的方式工作。