Haskell在列表中找到正确的数字

时间:2013-03-11 01:00:38

标签: list haskell compression

所以我想在这个函数中添加两个参数,一个列表以及我要打印的项目的位置。

listNumber [1,2,3,4,5,6] 2
>> 3

我这样做了

numberList :: (List a) => a -> a -> a
numberList a b = [x | x <- a !! n, n <- b]

我不知道我的错误在哪里。

2 个答案:

答案 0 :(得分:4)

我认为这是一种有趣的方式 如果我们暂时忽略类型签名并查看函数:

numberList a b = [x | x <- a !! n, n <- b]

我们看到n在list-comprehension的第一个条件中被调用:

x <- a !! n 

但是n仅在此之后定义,在第二个条件中:

n <- b

这会导致错误:不在范围内:`n'

所以要做的第一件事可能是切换第一个和第二个条件:

numberList a b = [x | n <- b, x <- a !! n]

现在向GHCi询问类型,我们得到:

Prelude> :t numberList
numberList :: [[t]] -> [Int] -> [t]

GHC希望参数a是列表列表,参数b是int的列表。这是因为n是从b中绘制的,并且列表理解中&lt; - 右侧的任何内容都必须是列表。由于n用作!!的参数,GHC假定n是int,b是int的列表。

现在GHC假设x也来自某种列表。所以我们知道GHC假设!! n是一个清单。但是从定义来看,一个!! n是位置n的列表a的元素,我们看到为什么GHC假定a是列表列表 - 因为GHC假定列表a的元素在位置n是从中绘制x的列表。

这是一个有效的例子:

Prelude> numberList [[1,2,3,4,5,6]] [0]
[1,2,3,4,5,6]

这里GHC确实向我们展示了位置0的列表a的元素,即列表[1..6]。不幸的是,这不允许我们按照我们的意愿方便地进入列表中的位置。另一种仍然使用列表推导的方法可能是定义一个新列表'c',其中包含我们所追求的元素(a !! n)并从这个新列表中绘制x,如下所示:

Prelude> let numberList a b = [x | n <- b, let c = [a !! n], x <- c]
Prelude> numberList [1,2,3,4,5,6,3] [2]
[3]
但是,这似乎有点令人费解,因为我们可以简单地使用!!直接得到位置b的元素:

Prelude> let numberList a b = a !! b
Prelude> numberList [1,2,3,4,5,6] 2
3

答案 1 :(得分:3)

  

所以我想在这个函数中添加两个参数,一个列表以及我要打印的项目的位置。

>>> listNumber [1,2,3,4,5,6] 2
3

好。第一步:你有一个非常混乱的类型签名。

numberList :: (List a) => a -> a -> a

这不应该被忽视。从良好的类型签名开始是掌握Haskell和类似语言中的良好编程技术的基本技能。

首先,您需要一个具有两个输入的函数。

numberList :: a -> b -> c

接下来,您希望第一个输入是“列表”。我们不知道这个列表包含什么,所以我们只使用类型参数a。撰写“a列表”的方法是[a]

numberList :: [a] -> b -> c

您希望第二个输入为“位置”。这可能是Int

numberList :: [a] -> Int -> c

最后,您希望结果成为列表的元素。因此它具有相同的类型a

numberList :: [a] -> Int -> a

我不知道你在哪里获得(List a) =>类型签名的部分,但它完全是假的,除非你使用的是一些你没有告诉我们的自定义库。如果您正在攻读Haskell大学课程,这很有可能。

我们有一个类型签名,可能很方便知道这是否已经为我们实现了。停止!霍格时间。在http://haskell.org/hoogle中输入类型签名[a] -> Int -> a。事实证明,您正在尝试实施!!