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

Chi*_*irs 3 haskell

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

我试图做的是这样的:

import Data.Matrix

newtype Puzzle = Matrix Char

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

[... more functions using 'Matrix Char']
Run Code Online (Sandbox Code Playgroud)

什么给了我

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)’
Run Code Online (Sandbox Code Playgroud)

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

Sho*_*hoe 7

使用typenewtype.前者创建一个类型别名,后者是一个新类型声明.具体newtype是一种特殊情况data,其中新类型表示现有类型的"包装器"(这是可以由编译器优化的情况).


Eri*_*lun 7

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

\n\n
import Data.Matrix\n\nnewtype Puzzle = Puzzle (Matrix Char)\n\ncomplete :: Puzzle -> Bool\ncomplete (Puzzle matrix) = \'-\' `elem` toList matrix\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

此外,Jeffrey 是对的,它比\xe2\x80\x94newtype更相似,提供了一些性能优化,但受到更多限制,并且稍微影响程序评估语义。您最好阅读 Haskell 中定义类型和类型别名的所有各种方法。datatypenewtypedata

\n\n

就您而言,您不妨datanewtype不改变程序行为的情况下进行替换;该程序的其余部分应继续以相同的方式工作。

\n\n

另请参阅:关于类型安全的 Haskell 类型与 newtype

\n