如何获取Haskell列表中的元素?

时间:2015-05-10 19:13:38

标签: list haskell

我想创建一个在String类型列表中查找[(String, Int)]的函数,并返回与Int配对的String

像这样:

λ> assignmentVariable "x" [("x", 3), ("y", 4), ("z", 1)]
3

以下是我尝试的内容:

assignmentVariable :: String -> [(String, Int)] -> Int
assignmentVariable [] = error "list is empty"
assignmentVariable n (x:xs) = if x == n
                              then xs
                              else assignmentVariable

我怎么写这个?

3 个答案:

答案 0 :(得分:7)

让我们来看看发布的代码:

assignmentVariable::String -> [(String, Integer)] -> Integer
assignmentVariable [] = error "list is empty"
assignmentVariable n (x:xs) = if x == n then xs else ...

第一个等式只有一个参数,而第二个等式有两个。让我们解决这个问题。

assignmentVariable::String -> [(String, Integer)] -> Integer
assignmentVariable _ []     = error "list is empty"
assignmentVariable n (x:xs) = if x == n then xs else ...

由于我们执行x == n,因此这些变量必须属于同一类型。 但是,n::Stringx::(String,Integer)。我们需要在比较之前将x拆分为其组件。

assignmentVariable::String -> [(String, Integer)] -> Integer
assignmentVariable _ []         = error "list is empty"
assignmentVariable n ((m,x):xs) = if m == n then xs else ...

结果xs是一个列表,而不是类型签名所暗示的Integer。你只想要x

assignmentVariable::String -> [(String, Integer)] -> Integer
assignmentVariable _ []         = error "list is empty"
assignmentVariable n ((m,x):xs) = if m == n then x else ...

最后,递归调用。在m/=n时,我们想要尝试列表xs中的其他对,所以:

assignmentVariable::String -> [(String, Integer)] -> Integer
assignmentVariable _ []         = error "list is empty"
assignmentVariable n ((m,x):xs) = if m == n 
                                  then x
                                  else assignmentVariable n xs

答案 1 :(得分:2)

您希望在对上进行模式匹配。

assignmentVariable expected ((key, value) : rest)

如果变量名称与预期名称匹配,则该对的第一个元素......

  = if key == expected

返回关联值,即该对的第二个元素。

    then value

否则,您尝试在列表的其余部分中找到该值。

    else assignmentVariable expected rest

您可以在没有模式匹配的情况下实现它,当然:

assignmentVariable expected list
  = if expected == fst (head list)
    then snd (head list)
    else assignmentVariable expected (tail list)

但是,这不是Haskell代码中的常用样式。

此功能也存在于Prelude中,名称为lookup

答案 2 :(得分:1)

实际上,你已到了一半!

首先,最好是制作更通用的类型签名,以及更好的名称:

myLookup :: (Eq a) => a -> [(a, b)] -> b

你已经完成了[]的边缘情况的整理,但你还没有完成:

myLookup _       []     = error "myLookup: empty list."
myLookup n  ((x, b):xs) = if x == n
                          then b
                          else myLookup n xs

你的问题就是你在else之后的问题:你没有递归调用函数,你返回的函数没有任何意义 - 你需要用不同的参数再次调用它复发。

如果您想进行改进,请尝试为类型Eq a => a -> [(a, b)] -> Maybe b创建类似的功能以进行挑战。