Haskell 如何在可能输出的列表中查找最大元素
此代码有效Haskell 如何在可能输出的列表中查找最大元素,haskell,maybe,Haskell,Maybe,此代码有效 max_elem :: (Ord a) => [a] -> a max_elem [x] = x max_elem [] = error "No elements" max_elem (x:xs) |x > max_elem xs = x |otherwise = max_elem xs 我想要它,所以如果它们没有元素,它什么也不返回,最大元素只有x 我尝试了以下方法 max_elem :: (Ord a) => [a] ->
max_elem :: (Ord a) => [a] -> a
max_elem [x] = x
max_elem [] = error "No elements"
max_elem (x:xs)
|x > max_elem xs = x
|otherwise = max_elem xs
我想要它,所以如果它们没有元素,它什么也不返回,最大元素只有x
我尝试了以下方法
max_elem :: (Ord a) => [a] -> Maybe a
max_elem [x] = Just x
max_elem [] = Nothing
max_elem (x:xs)
|x > max_elem xs = Just x
|otherwise = max_elem xs
我犯了以下错误。请建议修复此问题
• Couldn't match expected type ‘a’ with actual type ‘Maybe a’
‘a’ is a rigid type variable bound by
the type signature for:
max_elem :: forall a. Ord a => [a] -> Maybe a
at <interactive>:208:13
• In the second argument of ‘(>)’, namely ‘max_elem xs’
In the expression: x > max_elem xs
In a stmt of a pattern guard for
an equation for ‘max_elem’:
x > max_elem xs
• Relevant bindings include
xs :: [a] (bound at <interactive>:211:13)
x :: a (bound at <interactive>:211:11)
max_elem :: [a] -> Maybe a (bound at <interactive>:209:1)
•无法将预期类型“a”与实际类型“可能a”匹配
“a”是一个刚性类型变量,由
以下项的类型签名:
马克斯·埃伦:对于所有a。Ord a=>[a]->可能是a
时间:208:13
•在“(>)”的第二个参数中,即“max_elem xs”
在表达式中:x>max_elem xs
在图案保护的stmt中
“max_elem”的方程式:
x>最大元素x
•相关绑定包括
xs::[a](绑定时间:211:13)
x::a(绑定时间:211:11)
马克斯·埃利姆::[a]->可能是a(绑定在:209:1)
错误消息非常清楚,足以解决您的问题
|x > max_elem xs = Just x
问题是您将x
这是a
与max\u elem
这是可能是a
进行比较。这就是为什么你会收到这样的错误信息。您可以使用下面的代码解决这个问题
max_elem :: (Ord a) => [a] -> Maybe a
max_elem [] = Nothing
max_elem (x:xs) = case (max_elem xs) of
Nothing -> Just x
Just y -> if x > y then Just x else Just y
由于这一行,您得到了错误:
x>max_elem xs
max_elem xs
具有类型可能是a
,其中a
是列表的一个元素。它具有类型a
。不能比较不同类型的值<代码>a和可能a
是不同的类型。见Haskell等式表:
=
运算符替换为
,您将得到相同的表
您可以通过将x>max_elem xs
替换为Just x>max_elem xs
来解决代码中的问题。这对你有意义吗
如您所见,可能一个
数据类型有Ord a=>Ord(可能是)
实例,这实际上非常方便!因此,您可以以更简洁的方式实现您的功能,以利用此Ord
实例:
max_elem :: Ord a => [a] -> Maybe a
max_elem = foldr max Nothing . map Just
但是,如果您关心性能,这可能不是最有效的解决方案。我们可以概括此任务,并使用所有可折叠的
解决方案。因此,我们在这里使用折叠某种可折叠结构的函数。我们可以通过函数max来实现这一点。只是
,作为初始元素
无:
max_elem :: (Ord a, Foldable f) => f a -> Maybe a
max_elem = foldr (max . Just) Nothing
注意,这是因为Haskell将可能
定义为Ord
的一个实例,假设a
是Ord
的一个实例,并且它以无
比任何仅
元素小的方式实现它
这使得上述定义可能有点“不安全”(从这个意义上说,我们在这里依赖这样一个事实,即从我们有一个Just x
的那一刻起,max
将选择这样的Just x
,而不是Nothing
)。当我们使用min
时,这将不起作用(除非使用一些技巧)
我们还可以使用模式保护,从而以不同的方式解决列表为空的情况,如:
max_elem :: Ord a => [a] -> Maybe a
max_elem [] = Nothing
max_elem l = Just (maximum l)
问题是
x>max_elem xs
max_elem xs
是可能是a
,而不是a
,这意味着它可能不返回任何内容。但是,您知道如果xs
为空,它只会返回Nothing
,但是您知道xs
不会为空,因为您匹配了使用[x]时它会返回的情况。您可以通过编写“非空”最大值来利用这一事实:
或者,使用max
:
max_elem_ne :: Ord a => a -> [a] -> a
max_elem_ne m [] = m
max_elem_ne m (x:xs) = max_elem (max m x) xs
您可以将第一个参数视为“到目前为止”看到的最大值,将第二个列表参数视为其他候选列表
在最后一种形式中,您可能已经注意到,max\u elem\u ne
实际上是一个左折叠,因此您甚至可以只写:
max_elem_ne :: Ord a => a -> [a] -> a
max_elem_ne = foldl' max
现在,使用max\u elem\u ne
,您可以编写原始max\u elem
:
然后你可以写:
max_elem :: Ord a => [a] -> Maybe a
max_elem [] = Nothing
max_elem (x:xs) = Just (max_elem_ne x xs)
因此,您不必进行任何无关的检查(就像您在结果上进行冗余模式匹配时所做的那样),而且整个过程都是类型安全的
您还可以使用uncon::[a]->可能(a[a])
实用程序函数和fmap
和uncurry
来编写:
max_elem :: Ord a => [a] -> Maybe a
max_elem = fmap (uncurry max_elem_ne) . uncons
在“(>)”的第二个参数即“max_elem xs”中,无法将预期类型“a”与实际类型“Maybe a”匹配。我似乎很清楚您可以尝试导入数据。列表(findIndex)
和findIndex(=最大x)x
,但最好找到您的错误。我确实更喜欢将特定操作划分为特定函数。有计算,有错误检查和输入验证。在我看来,在一个单独的函数中,每一个函数都更干净。我会使用,否则只使用y
,否则我们会重新计算最大值,导致指数爆炸@谢谢!已编辑。“max_elem[x]=Just x”可以是skipped@max630谢谢编辑。fmap最大值(如果为空x,则没有其他值,只有x)
可能更简单。不需要将列表中的每个元素都包装在中,只需要一个非空的列表本身。好吧,在现实世界中,我不会首先对列表使用maximum
函数。与maximum
函数的低效性相比,将每个元素包装到maximum
中的成本微不足道,后者很可能包含空间泄漏。maximum
不过是使用Max
monoid对foldMap
进行包装;这和你上面写的没什么不同。是的,正如我在回答中所说的,我的实现也不完美。它也有同样的问题。但是我想Haskell初学者暂时不要深入研究这些事情是可以的。对不起,我想回来并注意我的建议也可以简化为如果为空x,则没有其他最大x
,因为最大值
基本上只是假设折叠不会重新折叠
max_elem :: Ord a => [a] -> Maybe a
max_elem = fmap (uncurry max_elem_ne) . uncons