data Identifier = Identifier [Num:(Char|Num)]
我正在尝试做类似Haskell中上面的代码的事情。我想为列表创建一个数据类型,该数据类型必须以数字开头,但尾部可以包含小写字符或数字。
答案 0 :(得分:4)
在Haskell中,列表不是“特殊”类型。实际上,可以这样定义它:
data List a = Empty | Cons a (List a)
因此,这意味着编译器没有必须了解列表是什么以及列表如何工作。对于Haskell,[a]
只是[] a
的另一种表示形式,它只是查看列表的类型构造函数。因此,这意味着对于编译器[a : b]
,因为类型是荒谬的,因为(:)
是 not 类型构造函数,因此它是 data构造函数
您可以将第一个字符作为单独的参数进行建模,例如:
data Identifier = Identifier Int [Either Int Char]
例如,您可以使用以下方式以文本形式表示您的Identifier
:
import Data.Char(intToDigit)
class Render a where
render :: a -> String
instance Render Identifier where
print (Identifier n ns) = intToDigit n : map iprint ns
where iprint (Left a) = intToDigit a
iprint (Right b) = b
这里我们的Identifier
数据类型因此排除了两种情况:
Char
开头的标识符。您可能还需要定义Digit
类型和Lower
类型,它们分别类似于Int
和Char
的子集,以进一步限制可能的值类型,因为现在Int
可以具有[0..9]
范围之外的值,并且Char
可以具有任何字符。
您还可以编写函数以将字符串解析为Identifier
。实际上,通过适当地“工程化”数据类型,可以排除很多本来不可能的值,因此编译器可以帮助您确保函数 not 不会返回应考虑的值无效。
Haskell的某些库中也使用了上述技术。例如,Data.List.NonEmpty
模块定义了data constructor (:|)
:
data NonEmpty a = a :| [a]
因此,这里再次定义了一个NonEmpty
列表,该列表的构造函数强制一个NonEmpty
具有一个元素,以及一个(可能为空)剩余元素的列表。