list - 如何使用自定义版本的List : `data List a = Nil | Cons a (List a)` ?

标签 list haskell types syntax custom-data-type

此问题基于 Graham Hutton 所著的《Programming in Haskell》一书第二版中的“Declaring Types and Classes”一章中的示例。

数据声明为: 数据列表 a = Nil |缺点(列表a)

使用此声明的示例函数是:

len :: List a -> Int
len Nil = 0
len (Cons _ xs) = 1 + len xs

但无论我尝试什么,我似乎都无法使用函数len:

  • len 缺点 1 缺点 2 缺点 3
  • 长度1
  • len 缺点
  • 长度 (1)
  • 长度[1,2]
  • len 缺点 [1]
  • len (1,2)
  • len 缺点 (1,2)
  • len 缺点 1 2
  • len(缺点(1,2))
  • len(缺点 1 2)

我是否错过了 lenCons 的任何排列?或者这个例子根本行不通?

最佳答案

您传递给 len 的参数不是 List。列表末尾有 Nil,因此列表的形式为 NilCons … NilCons … (Cons … Nil )Cons … (Cons … (Cons … Nil)) 等。因此最终对于每个列表,列表的末尾都会标记为 NilNil 相当于 Haskell 的 [a] 类型的 []

此外,例如,您不能传递 len Cons 1 Nil,因为这样它将被解释为 ((len Cons) 1) Nil。该参数应该是一个列表。通过使用括号,您可以将其写为 len (Cons 1 Nil)

对于给定的示例数据,您可以将其重写为:

  • len Cons 1 Cons 2 Cons 3len (Cons 1 (Cons 2 (Cons 3 Nil)))
  • len 1len(缺点 1 无)
  • len 缺点len Nil
  • len (1)len(缺点 1 无)
  • len [1,2]len(缺点 1(缺点 2 无))
  • len 缺点 [1]len(缺点 1 无)
  • len (1,2)len(缺点 1(缺点 2 无))
  • len Cons (1,2)len (Cons 1 (Cons 2 Nil))
  • len Cons 1 2len (Cons 1 (Cons 2 Nil))
  • len(缺点(1,2))len(缺点 1(缺点 2 无))
  • len(缺点 1 2)len(缺点 1(缺点 2 无))

您还可以使用OverloadedLists [haskell-doc]扩展以使用列表语法代替。在这种情况下,您需要实现 IsList类型类别:

{-# LANGUAGE <b>TypeFamilies</b> #-}

import GHC.Exts(IsList(..))

data List a = Nil | Cons a (List a)

instance <b>IsList (List a)</b> where
    type Item (List a) = a
    toList Nil = []
    toList (Cons x xs) = x : toList xs
    fromList [] = Nil
    fromList (x:xs) = Cons x (fromList xs)

如果您随后启用 OverloadedLists 扩展,则可以将它们写为列表文字:

{-# LANGUAGE <b>OverloadedLists</b> #-}

-- …

main = print (len <b>[1,2]</b>)

关于list - 如何使用自定义版本的List : `data List a = Nil | Cons a (List a)` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63098044/

相关文章:

python - 检查列表是否为空的最快方法是什么?在什么情况下一种方法优于另一种方法?

python - Python 中是否有可以替代 "zip"函数的函数?

sql - 搜索多个列表以查找缺失的条目

haskell - 设计代码以避免维护期间重写

typescript :严格检查 "Any"

python - 如何将类对象 append 到列表

SICP 练习中的 Haskell 数字类型层次结构

sqlite - 将 ReaderT 和 runReaderT 与 SQLite 一起使用?

types - 扩展库中的固有类型是不好的形式吗?

c# - 如何使用反射访问私有(private)基类字段