【问题标题】:defining a type for a nonempty list为非空列表定义类型
【发布时间】:2013-09-14 06:51:58
【问题描述】:

我正在尝试习惯在 Haskell 中定义递归类型。作为一个简单的练习,我认为定义一个非空列表数据类型会很容易(并且可能很有用)。

这是我的尝试:

data NonemptyList a = Singleton a | Cons (Singleton a) (NonemptyList a)

导致编译错误:

不在范围内:类型构造函数或类 `Singleton'
失败,已加载模块:无。

以下代码可以编译,但不适合我。我不能确切地解释为什么不。

data NonemptyList a = Singleton a | Cons  a (NonemptyList a)

谁能帮我澄清一下?欢迎任何cmets。

谢谢

【问题讨论】:

  • 在你的例子中,Singleton 是一个数据构造函数——你使用这些来定义值。定义类型时,您使用类型构造函数。这两个是不同的概念,不能混用。我只能说第二个选项(有效的那个)非常好,我不知道你为什么不喜欢它。
  • 构造函数的字段是类型,而不是构造函数。注意Cons 的第二个字段是NonemptyList aNonemptyList a 是一种类型。
  • 感谢您快速清晰的回复。我想我现在明白我的错误了。在下面的代码中,Singleton 是一个数据构造函数,SingletonType 和 NonemptyListType 是类型构造函数。此代码编译。 data SingletonType a = Singleton a data NonemptyListType a = SingletonType a |缺点 (SingletonType a) (NonemptyListType a)

标签: haskell recursion types


【解决方案1】:

这是因为您在需要类型构造函数的地方使用了Singleton(数据构造函数)。在此示例中,SingletonCons 是数据构造函数,Nonemptylist 是类型构造函数。这两个概念很容易混淆,因为定义同名的数据构造函数和类型构造函数是很常见的,例如data Foo a = Foo a.

在这种情况下,data NonemptyList a = Singleton a | Cons a (NonemptyList a) 可能是要使用的正确代码。

【讨论】:

    【解决方案2】:

    附带说明,定义非空列表的更简单方法是:

    data NonEmpty a = NonEmpty { head :: a, tail :: [a] }
    

    最流行的非空列表包是semigroups 包,它与Data.List.NonEmpty 模块中的上述定义类似。

    【讨论】:

    • 我现在明白了。这本质上与:inline 'data NonEmpty' a = Nonempty' a [a]` 一样清晰和简单。
    • @sitiposit 没错。我只包含字段访问器名称只是为了免费获得这两个功能。
    猜你喜欢
    • 1970-01-01
    • 2013-02-01
    • 2016-09-05
    • 2012-10-07
    • 2017-01-28
    • 1970-01-01
    • 2020-05-09
    • 2015-02-26
    • 2017-11-05
    相关资源
    最近更新 更多