为什么在Haskell中最大值(8,1)= 1?

Sup*_*der 8 haskell max foldable

我刚刚开始学习Haskell。据我所知,maximum给出了整数列表的最大值。因此,maximum [2,5,7,1]给出7。但是为什么通过给出元组输入,max总是给出第二个元素?例如,maximum (8,1)给1同样的事情发生的sum (8,1)product (5,2)minimum (4,5)...所有给出的元组的第二个元素。因此,有人可以向初学者解释为什么会发生这种情况吗?

Wil*_*sem 8

简短答案:对于2元组,Foldable实例仅考虑第二项。maximum因此,该函数将始终返回2元组的第二项。

因为2元组是的实例Foldable。实际上,它定义为[src]

instance Foldable ((,) a) where
    foldMap f (_, y) = f y

    foldr f z (_, y) = f y z
Run Code Online (Sandbox Code Playgroud)

maximum本质上是一个foldr相似的模式。它的实现等效于:

maximum = foldr1 max
Run Code Online (Sandbox Code Playgroud)

在哪里foldr1实现为:

foldr1 f = fromMaybe (error "…") . foldr mf Nothing
    where mf x m = Just (case m of
                             Nothing -> x
                             Just y  -> f x y)
Run Code Online (Sandbox Code Playgroud)

因此,对于2元组,它将实现为:

maximum (_, y) = fromMaybe (error "…") (mf y Nothing)
    where mf x m = Just (case m of
                             Nothing -> x
                             Just y  -> max x y)
Run Code Online (Sandbox Code Playgroud)

因此,这里我们mfy(作为x参数)和Nothing作为调用m。在case … of …这个用火柴Nothing和回报x。因此,两个元组的最大值定义为:

maximum (_, y) = fromMaybe (error "…") (Just y)
Run Code Online (Sandbox Code Playgroud)

因此更短:

-- maximum for a (a, b)
maximum (_, y) = y
Run Code Online (Sandbox Code Playgroud)

  • @TheInnerLight因为类型通常不同。例如,“ maximum(“ hello”,4)“不能同时考虑这两个元素。这里的类型是`(,)String Int`,`Foldable`可以将其视为类似于容器的类型`(,)String`,其元素恰好具有`Int`。我并不十分相信在库中允许`Foldable((,)a)`是一个好主意,但是如果我们允许的话,我们就没有类型安全的选择,只能考虑这对的第二个组成部分。 (3认同)
  • 为了扮演魔鬼的拥护者,我认为`Foldable`实例不错,不是因为您经常会折叠一个单元素容器,而是因为它强调了一个事实,即元组不仅仅是列表上的一个小变化。“最大(8,1)”不返回“ 8”的事实应迫使您停下来,问问自己为什么首先要有一个元组。 (2认同)