【问题标题】:Why isn't composing two functions working?为什么组合两个函数不起作用?
【发布时间】:2015-09-19 01:49:01
【问题描述】:

除了可读性和失去一般性之外,以下定义有什么问题:

maxPlusOne :: (Ord a, Num a) => a -> a -> a
maxPlusOne = (1+) . max

编译器会抱怨它不能从+ 推导出Num (a -> a)。 但在我看来它需要的是Num a => a -> a,这正是(1+)的类型。

这是错误:

<interactive>:5:52:
    Could not deduce (Num (a -> a)) arising from a use of ‘+’
    from the context (Ord a, Num a)

【问题讨论】:

  • Num a =&gt; a -&gt; a 不是(1+) 的类型。
  • @ErikAllik:是的。如果我在 ghci 中输入 :t (1+),它会告诉我 (1+) :: Num a =&gt; a -&gt; a - 就是这样。
  • (但那当然和Num a =&gt; Num (a -&gt; a)不一样)

标签: haskell types


【解决方案1】:

让我们检查各个类型:

max :: (Ord a) => a -> a -> a

好的,这接受a,并返回一个接受a 并返回a 的函数。

(1 +) :: (Num a) => a -> a

这很简单。它需要一个数字a 并添加一个。

如果我们记得 a . b 等同于 \q -&gt; a (b q),我们会从您的定义中得到:

(1 +) . max   ==   \q -> 1 + (max q)

你能看出问题吗?您将a -&gt; a 类型传递给(1 +)因为max 只得到一个参数。


这是修复它的方法,同时保持无点风格。

maxPlusOne = (.) (1 +) . max

这扩展为

maxPlusOne = \q -> (1 +) . max q

扩展为

maxPlusOne = \q1 -> \q2 -> 1 + (max q1 q2)

你想要的功能是什么。


您还可以定义另一种类型的组合:

(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.:) f g a b = f (g a b)

然后定义

maxPlusOne = (+ 1) .: max

【讨论】:

    【解决方案2】:

    我认为您对. 的解释过于数学化(如f“之后”g)。 . 很简单:

    (.) :: (b -> c) -> (a -> b) -> a -> c
    

    所以它的语义是它接受一个参数a,然后在a上调用g,然后在g上调用f。您可以将其定义为:

    (.) f g x = f $ g x
    

    虽然提出了 Haskell 扩展(如 this one),它使用类型系统来派生要传输多少“参数”,并且有些人已经在模板 Haskell 中编写了此功能,但这不是标准功能。

    如何解决?

    只需在函数头部查询至少一个参数x

    maxPlusOne :: (Ord a, Num a) => a -> a -> a
    maxPlusOne x = (1+) . max x
    

    或完全指定:

    maxPlusOne :: (Ord a, Num a) => a -> a -> a
    maxPlusOne x y = (1+) $ max x y
    

    或在(.) 上使用扩展名。

    如果你使用jaspervdj's extension

    maxPlusOne :: (Ord a, Num a) => a -> a -> a
    maxPlusOne = (1+) $.$ max
    

    【讨论】:

    • (.)理解为fg之后并没有错。只是,在f . gfg 中只需要一个参数——实际上所有 Haskell 函数只需要一个参数。
    • @duplode 我认为这是许多初学者遇到的问题:所有 Haskell 函数都采用一个参数的想法,这里似乎就是这种情况。
    • 你指的是哪个“(.)上的扩展”?
    • @duplode:但在数学中,通常这与g 的参数数量无关。正如 AJFarmar 所说,由于 Haskell 的柯里化方面,. max 输出一个函数 Int -> Int
    • 我的意思是,您的陈述不正确,可能会进一步混淆 OP。
    猜你喜欢
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多