重要的是,我必须警告我正在学习Haskell,而且我不知道预先构建的许多函数,所以我将使用到目前为止学到的东西。
我写过这个,我能做的最好的方法,尝试了很多但却无法通过。
minFst :: [(t, t1)] -> [(t, t1)]
minFst [] = []
minFst ((a,b):(a1,b1):xs) = if (a >= a1) then (a,b): minFst xs
else (a1,b1): minFst xs
这个功能需要的是:
[(10,21), (3, 55), (66,3)] = [3,55] -- Gives me the tuple with the lowest 'a'
编辑:在删除ord函数的建议之后,只有当我调用minFst时才会给我编译错误:
minFst [(1,2),(4,5),(5,7),(2,5),(10,6)]
[(4,5),(5,7)*** Exception: Helder.hs:(584,1)-(586,72): Non-exhaustive patterns in function minFst
我希望你可以帮助我解决这个问题,如果这篇文章有问题,请告诉我,我会改变它,不要一开始就贬低我。
答案 0 :(得分:4)
使用一些内置函数Data.List.minimumBy
,Data.Ord.comparing
和fst
非常简单:
import Data.List (minimumBy)
import Data.Ord (comparing)
minFst :: Ord a => [(a, b)] -> (a, b)
minFst xs = minimumBy (comparing fst) xs
或者你可以点免费地写它
minFst = minimumBy (comparing fst)
既然你说你不能将这些功能用于你的任务,那么让我们自己编写一个简单的最小函数
myMin :: Ord a => [a] -> a
myMin [] = error "Empty list!"
myMin [x] = x
myMin (x:y:xs) = if x < y then myMin x xs else myMin y xs
现在,这不适用于您的情况,因为您想要找到具有最小元素的元组,因此您必须稍微修改此代码
myMin :: Ord a => [(a, b)] -> (a, b)
myMin [] = error "Empty list!"
myMin [x] = x
myMin ((a1, b1):(a2, b2):xs) = {- Implementation here -}
我会让你自己填写。现在,如果想要所有具有最小第一个元素的元组(可能有多个元素),您可以通过首先计算最小值,然后过滤具有第一个元素的所有列表来低效地执行它。这不是最好的算法,因为你必须两次搜索列表。
如果你想一次性完成,它会变得有点棘手。在这些情况下,您希望在遍历时累积当前最小值。每当你需要累积值时,你需要另一个参数,但最好将它隐藏在本地函数内,而不是模块级函数中。我将向您展示一个整数列表的示例:
minimums :: [Int] -> [Int]
minimums xs = go xs []
where
go [] acc = acc
go (x:xs) (y:ys)
| x == y = go xs (x:y:ys) -- Accumulate the x
| x < y = go xs [x] -- Reset if new min found
| otherwise = go xs (y:ys) -- Ignore x if greater than y
> minimums [1, 2, 3, 2, 1]
[1, 1]
对于Int
来说并不是很令人兴奋,但它会为您提供使用元组执行此操作所需的基本模式。像内置minimum
一样,这个函数不能是懒惰的,它必须评估列表中的每个元素,所以不要将它传递给无限列表,否则你将永远等待它完成。< / p>