创建一个类型,该类型是其他类型的子集

时间:2015-10-24 15:51:17

标签: haskell types

如何创建属于其他类型子集的类型?我想要一个只包含字母数字字符的字符串类型。

所以我想要这样的东西

type AlphNumString = [AlphaNumChar]
data AlphaNumChar = ???? filter (isAlphaNum) Char ????

3 个答案:

答案 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将是表示字母数字字符的类型。该类型的每个元素都包含一个字符和一个字符为字母数字的证据。