我刚刚开始学习Haskell。据我所知maximum
给出了整数列表的最大值。因此,maximum [2,5,7,1]
给出7。但是为什么通过给出一个元组输入,max总是给出第二个元素?例如,maximum (8,1)
给出1。sum (8,1)
,product (5,2)
,minimum (4,5)
也会发生同样的事情...都给出了元组的第二个元素。因此,有人可以向初学者解释为什么会发生这种情况吗?
为什么在Haskell中最大值(8,1)= 1?
•
问答
dqsj09021013 回答:为什么在Haskell中最大值(8,1)= 1?
简短答案:对于2元组,Foldable
实例(仅)将第二项考虑在内。 maximum
函数因此将始终返回2元组的第二项。
因为2元组是Foldable
的实例。确实是defined as [src]:
instance Foldable ((,) a) where foldMap f (_,y) = f y foldr f z (_,y) = f y z
maximum
本质上是一种文件夹模式。它的实现等效于:
maximum = foldr1 max
foldr1
的实现方式为:
foldr1 f = fromMaybe (error "…") . foldr mf Nothing
where mf x m = Just (case m of
Nothing -> x
Just y -> f x y)
这意味着对于2元组,它将实现为:
maximum (_,y) = fromMaybe (error "…") (mf y Nothing)
where mf x m = Just (case m of
Nothing -> x
Just y -> max x y)
因此,在这里我们用mf
(作为y
参数)调用x
,将Nothing
称为m
。 case … of …
与Nothing
匹配并返回x
。因此,两个元组的最大值定义为:
maximum (_,y) = fromMaybe (error "…") (Just y)
因此更短:
-- maximum for a (a,b)
maximum (_,y) = y
,
Haskell中的字符串不是像Python中那样的多值容器。相反,它们更接近单个值的容器,例如Maybe a
或Either b a
:具有上下文的值。尽管Maybe
和Either
都可能没有值(Either
仅仅提供了比Maybe
更多的关于缺少值的信息)的概念,但元组却带有以下内容:有关值本身的信息。
类似(8,1
的值不包含两个值8
和1
。相反,8
是包含1
的容器的部分。
因此,元组是可折叠的,即使这样做是微不足道的。将类型(a,b)
的值减小为b
的值仅需返回类型b
的值,而不必担心如何处理其他类型b
的值,因为没有 。
>>> maximum (Just 5)
5
>>> minimum (Just 5)
5
>>> maximum (Right 5)
5
>>> minimum (Right 5)
5
>>> maximum (True,5)
5
>>> minimum (True,5)
5
与Maybe
或Either
相比,此类函数是带有元组的 total :
>>> maximum Nothing
*** Exception: maximum: empty structure
>>> maximum (Left 5)
*** Exception: maximum: empty structure
无论元组包含多少种类型,对于最给定的Foldable
实例,除最右边的元组之外的所有元组都将固定。
-- Actual instance for (a,b)
instance Foldable ((,y) = f y
foldr f z (_,y) = f y z
-- Instance for (a,b,c) if you wanted it
instance Foldable ((,) a b) where
foldMap f (_,_,y) = f y z