列表或元组元组的列表

时间:2013-01-14 09:57:14

标签: haskell tuples

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

我最接近的是这个。

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

使用类似的东西。

func [] 3

返回此内容。

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

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

非常感谢!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

关键是要提出正确的类型。

如果您需要[1, [2, [3, [4]]]]之类的内容,那么完全将无效,因为所有列表元素必须是相同的类型。

这是有道理的,因为当我从列表中抓取一个元素时,我需要知道它是什么类型之前我可以用它做任何事情(这是类型的全部点,它们告诉你你能做什么并且不能做任何事情。)

但是由于Haskell的类型系统是静态的,我需要知道它甚至是的类型,而不知道列表中的哪个元素,因为我抓住的列表索引可能直到该程序运行。所以无论我使用什么索引,我都必须得到相同类型的东西。

但是,可以像你想要的那样做一些事情:你想要一个可能是整数的数据类型,或者可能是一个列表:

type IntegerOrList a = Either Integer [a]

如果您不熟悉Either类型,某些Either l r的值Left x可能为x :: l,某些Right y可能为y :: r IntegerOrList a。所以[IntegerOrList Bool]是一种类型,其值可以是整数或某些列表。因此,我们可以列出这些内容:以下是[Left 7, Left 4, Right [True, False], Left 8, Right [], Right [False]] 类型的值:

Bool

好的,所以这是列表中的一个列表级别,但是我们不能将列表放在列表中的列表中 - 内部列表包含[IntegerOrList (IntegerOrList Bool)] s,它们不能是列表。如果我们改为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]]]]

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

I

关键是必须使用LIntegerOrLists构造函数标记每个项目是整数还是列表。现在列表的每个元素都是{{1}}类型,我们可以通过查看该构造函数来区分它。所以typechecker终于开心了。

答案 2 :(得分: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中拥有这样的结构,只需使用一些礼品包装
  • 这些结构几乎没用(尝试用它做点什么)