如何创建属于其他类型子集的类型?我想要一个只包含字母数字字符的字符串类型。
所以我想要这样的东西
type AlphNumString = [AlphaNumChar]
data AlphaNumChar = ???? filter (isAlphaNum) Char ????
答案 0 :(得分:7)
执行此操作的标准方法是使用所谓的“智能构造函数”。
首先,您定义一个与旧类型相同的新类型:
newtype AlphNumString = X String
接下来,您将编写智能构造函数:
toAlphNumString :: String -> AlphNumString
toAlphNumString txt = X (filter isAlphNum txt)
最后,您这样做toAlphNumString
是唯一方式来创建AlphNumString
。
module Foo (AlphNumString (), toAlphNumString, ...) where ...
请注意,不允许您像普通AlphNumString
一样使用String
;你不能在Haskell中创建像那样的“子类型”。所以你还需要另一个功能
fromAlphNumString :: AlphNumString -> String
fromAlphNumString (X txt) = txt
答案 1 :(得分:3)
这种类型的概念是基于某些谓词的其他类型的“子集”,称为优化类型。对于Haskell,这实现为LiquidHaskell。
但是,我认为这是一项持续的研究。在实践中,我将使用newtype和动态检查,正如MathematicalOrchid在他们的答案中所描述的那样。
答案 2 :(得分:0)
在依赖类型的语言中(Haskell还没有),你可以使用依赖对。
data Sigma : (t : Type) -> (t -> Type) -> Type where
MkSigma : (x : t) -> p x -> Sigma t p
data IsAlphaNum : (c : Char) -> Type where
MkIsAlphaNum : isAlphaNum c = True -> IsAlphaNum c
然后Sigma Char IsAlphNum
将是表示字母数字字符的类型。该类型的每个元素都包含一个字符和一个字符为字母数字的证据。