1

我正在编写一个 Haskell 函数,它接受一个字符串列表并返回一个包含前两个字符串的列表作为结果作为元组。所以一个示例输出将是:

listtuple ["bride", "zilla", "crazy", "women"] = [("bride", "villa")]
listtuple ["basketball", "football"] = [("basketball", "football")]

我想这样接近它的方式:

listtuple :: Eq a => [Str a] -> [(Str a, Str a)]
listtuple xs = [(x,y) | x <- xs !! 0, y <- xs !! 1]

本质上,我认为我可以只选择列表的第一个和第二个索引中的元素,但我遇到了错误。这里有什么帮助吗?

4

3 回答 3

10

简单的答案是

listtuple :: [a] -> [(a,a)]
listtuple (x:y:_) = [(x,y)]
listtuple _ = []

由于您的列表将始终包含一个项目或不包含一个项目,因此最好使用Maybe哪个服务器用于此目的。

listtuple2 :: [a] -> Maybe (a,a)
listtuple2 (x:y:_) = Just (x,y)
listtuple2 _ = Nothing
于 2012-10-11T04:57:02.577 回答
7

您可能想要做的是:

listtuple xs =
    let x = xs !! 0
        y = xs !! 1
     in (x, y)

请注意,这与您编写的内容不同。原因是您编写的列表理解转换为以下内容:

do x <- xs !! 0  -- Treat the first  element of xs as a list
   y <- xs !! 1  -- Treat the second element of xs as a list
   return (x, y)

这说明了问题:当它们不是列表时, 您将xs !! 0和视为列表。只是一个元素,所以如果你想声明等于,你使用:xs !! 1xs !! 0xxs !! 0

let x = xs !! 0
 in <some expression that uses x>

in 列表推导语法不会做同样的<-事情,我建议您在了解列表单子如何工作之前避免使用列表推导,因为编译器会将列表推导转换为列表单子。

现在,第二个问题是您使用(!!). 您应该避开偏函数,(!!)并专注于使用模式匹配来解决这些问题。执行您要求的惯用方法是对前两个元素进行模式匹配:

listtuple (x:y:_) = (x, y)

...除了在包含少于两个元素的列表上会失败。您可以通过将结果存储为 a 来防止这种情况Maybe,其中 aJust包装成功的结果并Nothing指示失败:

listtuple :: [a] -> Maybe (a, a)
listtuple (x:y:_) = Just (x, y)
listtuple _       = Nothing
于 2012-10-11T05:20:07.167 回答
1

我可以看到您的代码中有一些错误,但是如果您对代码为什么不起作用有具体问题,请告诉我。

首先,您提供的类型签名无效。String是一个无参数的数据结构,Str a什么都不是,当然除非你定义了一个Str自己命名的数据结构。s列表String也不需要您提供的等式约束,因为编译器已经知道它StringEq.

其次,您在 where 子句的位置(看起来像)使用列表理解语法。xs !! 0考虑 Haskell 将在绑定元素之前尝试评估x。因为这是一个列表推导,所以它可能不会立即失败,因为xs它是一个Strings 的列表(实际上是 的列表Char),但您最终会Char从 xs 的第一个和第二个字符串中提取 s 的元组。

这是一个使用模式匹配的简单解决方案,可以产生您想要的。

listtuple :: [a] -> [(a, a)]
listtuple (x:y:zs) = [(x, y)]

请注意,这不是一个完整的函数(即,如果您将一个少于两个元素的列表传递给它,它将导致错误)。这可以通过在将空列表或一个元素列表传递给它时返回空列表来完成,这是否符合您的预期目的?

这是一个替代版本,您可能会发现它适合您用来编写自己的版本的心智模型。

listtuple xs = [(x, y)]
            where
                x = xs !! 0
                y = xs !! 1
于 2012-10-11T04:55:46.823 回答