3

我只是想知道是否有可能创建一个返回与此类似的(希望是无限的)数字列表的函数。[1, [2, [3, [4]]]]。

我得到的最接近的是这个。

func list 0 = list
func list num = func newList (num-1) 
                where newList = list ++ [[num]]

这是使用这样的东西。

func [] 3

哪个返回这个。

[[3],[2],[1]]

现在我知道这不是无限的,也不是正确的顺序,但我只是想表明我至少在发布之前尝试了一些东西。:)

非常感谢!

4

3 回答 3

8

您不能编写这样的函数,因为列表的所有元素必须具有相同的类型。即使只有两个元素,您要创建的列表也不会进行类型检查:

Prelude> :t [1::Int,[2::Int]]

<interactive>:1:9:
    Couldn't match expected type `Int' with actual type `[Int]'
    In the expression: [2 :: Int]
    In the expression: [1 :: Int, [2 :: Int]]

第一个元素是 Int,第二个元素是 Int 列表,因此类型检查失败。

虽然你可以用元组来表达结果,例如

Prelude> :t (1::Int,(2::Int,(3::Int,4::Int)))
(1::Int,(2::Int,(3::Int,4::Int))) :: (Int, (Int, (Int, Int)))

您仍然无法编写函数,因为结果的类型会根据您希望拥有的元素数量而改变。让我们调用f假设函数:

f 1 :: (Int)
f 2 :: (Int,(Int))
f 3 :: (Int,(Int,(Int)))
...

类型f随参数变化,所以f不能写。

于 2013-01-14T10:19:30.853 回答
2

关键是想出正确的类型。

如果你想要类似的东西[1, [2, [3, [4]]]],那么这样做行不通的,因为所有列表元素都必须是相同的类型。

这是有道理的,因为当我从列表中抓取一个元素时,我需要知道它是什么类型,然后才能对它做任何事情(这是类型的全部意义,它们告诉你你能做什么和能做什么'不做某事)。

但是由于 Haskell 的类型系统是静态的,我需要知道它是什么类型,即使不知道它是列表的哪个元素,因为在程序运行之前我可能不知道我正在抓取的列表索引。所以无论我使用什么索引,我几乎都必须得到相同类型的东西。

但是,可以做一些非常像您想要的事情:您想要一个可能是整数或可能是列表的数据类型:

type IntegerOrList a = Either Integer [a]

如果您不熟悉Either类型,则值Either l r可以是Left xsomex :: lRight ysome y :: rIntegerOrList a其值为整数或某物列表的类型也是如此。所以我们可以列出这些东西:以下是 type 的值[IntegerOrList Bool]

[Left 7, Left 4, Right [True, False], Left 8, Right [], Right [False]]

好的,这是列表中的一级列表,但是我们还不能将列表放入列表中的列表中——内部列表包含Bools,它不能是列表。如果我们改为使用[IntegerOrList (IntegerOrList Bool)],我们将能够在列表中的列表中包含列表,但我们仍然无法获得进一步的结果。在我们的示例中,我们有一个列表,其中包含整数或列表的值,列表是包含整数或列表的值的列表,并且......我们真正想要的是类似的东西IntegerOrList (IntegerOrList (IntegerOrList ...,或者更简单地说,像:

type IntegerOrLists = Either Integer [IntegerOrLists]

但这是不允许的——类型同义词不能是递归的,因为这会产生无限大的类型,这会让糟糕的编译器感到困惑。但是,正确的数据类型可以是递归的:

data IntegerOrLists = I Integer | L [IntegerOrLists]

现在您可以构建这样的列表,混合整数和您类型的列表:

L [I 1, L [I 2, L [I 3, L [I 4]]]]

关键是每个项目是整数还是列表都必须使用IorL构造函数来标记。现在列表的每个元素都是 type IntegerOrLists,我们可以通过查看构造函数来区分它是什么。所以类型检查器终于高兴了。

于 2013-01-14T15:40:14.477 回答
1
{-# LANGUAGE ExistentialQuantification #-}

class Foo a

instance Foo Int
instance Foo [a]

data F = forall a. Foo a => F a

test = F [F (1 :: Int), F [F (2 :: Int), F [F (3 :: Int), F [F (4 :: Int)]]]]

这个例子显示

  • 你可以在 Haskell 中拥有这样的结构,只需使用一些礼品包装
  • 这些结构实际上是无用的(尝试用它做点什么)
于 2013-01-14T14:57:22.670 回答