我正在尝试使用过滤器(尽管我也可以使用map和/或foldr)来查找列表的max元素。
我尝试过滤掉小于max的每个数字,但它拒绝接受max作为过滤器参数。
这是我的代码:
max' :: Ord a => [a] -> a
max' xs = filter (< max) xs
这是我得到的错误:
* Couldn't match type `a' with `a0 -> a0 -> a0'
`a' is a rigid type variable bound by
the type signature for:
max' :: forall a. Ord a => [a] -> a
at Prog8.hs:50:1-25
Expected type: [a0 -> a0 -> a0]
Actual type: [a]
* In the second argument of `filter', namely `xs'
In the expression: filter (< max) xs
In an equation for max': max' xs = filter (< max) xs
* Relevant bindings include
xs :: [a] (bound at Prog8.hs:51:6)
max' :: [a] -> a (bound at Prog8.hs:51:1)
有没有一种方法可以在简单的过滤器函数中写入max'(或者可以将其与map或foldr结合使用)?
答案 0 :(得分:1)
一个空列表没有最大元素,因此您不能使用所提供的类型编写总函数。一个更明智的选择是
maximum' :: Ord a => [a] -> Maybe a
最简单的方法是使用foldl'
:
maximum' = foldl' gom Nothing where
gom Nothing new = Just new
gom (Just old) new
| old < new = Just new
| otherwise = Just old
但是您想要foldr
。由于foldl'
实际上是根据foldr
定义的,所以这很容易!
foldl' f b0 xs = foldr gof id xs b0
where
gof x r b = b `seq` r (f b x)
内联
maximum' xs = foldr gob id xs Nothing
where
--gob new r b = b `seq` r (gom b new)
gob new r b = seq b $ r $
case b of
Nothing -> Just new
Just old
| old < new -> Just new
| otherwise -> Just old
进行一些手动严格度分析,简化为
maximum' xs = foldr gob id xs Nothing
where
gob new r b = r $!
case b of
Nothing -> Just new
Just old
| old < new -> Just new
| otherwise -> Just old
一个小小的警告:如果这是家庭作业,而您上交我的解决方案,您的老师可能会变得可疑。有一种更简单的方法,它的效率也低得多,但我会让您搜索它。
答案 1 :(得分:-1)
因此,首先,您发现想要的是:
max' :: Ord a => [a] -> [a]
max' xs = filter (< maximum xs) xs
如果由于某种原因您绝对致力于无点样式,并且只想使用高阶函数进行编写,那么这也将起作用:
max' :: Ord a => [a] -> [a]
max' = flip filter <*> ((>) <$> maximum)
但是不要那样做,太糟糕了。只需重复两次参数即可。