1

我对 Haskell 很陌生,不知道如何解决我遇到的以下问题。

我必须实现以下函数“ca”,它接受一个列表和一个元素,并在输入元素之后删除列表中的所有其他元素:

ca:: Eq a => a -> [a] -> [a]

我不允许更改任何函数类型,并且到目前为止提出了以下代码:

ca x xs = let (ys, zs) = splitAt (elemIndex x xs) xs in ys 

这会产生以下错误:

couldn't match expected type 'Int' with the actual type 'Maybe Int'

现在我明白为什么会发生这个错误,但是我不明白如何修复它。任何帮助,将不胜感激。

4

3 回答 3

4

您可以使用该函数代替使用索引,该break函数在谓词第一次变为 的位置之前拆分列表True

> break (== 'x') "aabaaccxaabbcc"
("aabaacc","xaabbcc")

或者,由于您无论如何都要丢弃第二部分,因此您可以使用takeWhile.

> takeWhile (/= 'x') "aabaaccxaabbcc"
"aabaacc"
于 2014-04-15T12:22:21.647 回答
1

这应该进行类型检查,尽管该函数现在不安全:

import Data.List
import Data.Maybe (fromJust)

ca x xs = let (ys, zs) = splitAt (fromJust $ elemIndex x xs) xs in ys

原因是elemIndextype iselemIndex :: Eq a => a -> [a] -> Maybe Int 并且您想从中提取Int出来Maybe并将其传递给splitAt函数。这就是fromJust函数的作用。fromJust将从Just数据类型中提取值。

maybe您可以尝试使用或任何其他替代功能编写此功能的安全替代方案。

于 2014-04-15T12:19:55.487 回答
0

你可以这样做:

let 
  Just n = elemIndex x xs
  (ys, zs) = splitAt n xs
in ys

但是,如果指定的元素不存在,这将由于“模式匹配失败”而引发异常。更好的方法是:

case elemIndex x xs of
  Just n  -> let (ys, zs) = splitAt n xs in ys
  Nothing -> {- decide what to do if there's no match! -}

但是,我同意哈马尔的观点。您并没有真正尝试将列表分成两部分;你只对其中一个部分感兴趣。所以与其在列表中寻找,找到你想要的元素,返回它的索引,然后再次在列表中寻找,为什么不直接使用breakortakeWhile呢?

于 2014-04-15T12:32:50.723 回答