【问题标题】:Haskell function typeHaskell 函数类型
【发布时间】:2021-12-31 14:27:05
【问题描述】:

我现在正在尝试理解 Haskell 函数类型。 假设我想组合两个函数 f1 和 f2(假设我不知道它们的定义)。 f2 的函数签名。 f1 是:

f1 . f2 :: (Fractional (a -> a), Num a) => a -> (a -> a) -> a -> a

我如何阅读此签名,更具体地说,我如何知道如何将参数应用于此组合?

例如如何读取 f1 的类型信息。 f2 能够编写有效的表达式,例如

(f1 . f2 2) 3 4
(f1 2. f2 2) 4

【问题讨论】:

    标签: function haskell types


    【解决方案1】:

    那个签名意味着你没有正确组合它们。你不会得到类型error,因为理论上某些疯子可能会给函数一个Fractional 实例,但在现实生活中这永远不会发生。因此,没有一组参数可以应用于(f1 . f2) 来进行类型检查。

    相反,备份并查看f1f2 的类型。这些是什么?我预测它们都是双参数函数,因为你的类型是我写的时候得到的类型

    :t (/) . (+)
    (/) . (+)
      :: (Fractional (a -> a), Num a) => a -> (a -> a) -> a -> a
    

    你不能真正组合一个有两个参数的函数,因为组合是针对一个参数的函数。但是,如果您愿意,您可以在组合之前部分应用这些函数,以将它们变成单参数函数。这正是您在上一个示例中所做的,效果很好:

    Prelude> f1 = (/)
    Prelude> f2 = (+)
    Prelude> (f1 2 . f2 2) 4
    0.3333333333333333
    

    【讨论】:

    • 但是deriving via (Ap ((->) b) a) instance Num a => Num (b -> a) 和 Church 数字的实例都坐在那里求我写它们! :)
    • 从技术上讲,(/) . uncurry (+) 也是一种可能性。
    • @JosephSible-ReinstateMonica 比这更糟。它实际上是Fractional。为函数写一个recip 方法应该会特别有趣!
    • @WillNess 不就是recip = (recip .)吗?
    • 谢谢大家,也许是,我应该要求f1 . f2 :: (Num a, Num (a -> a)) => a -> (a -> a) -> a -> a 代替。 @amalloy 我从您的回答中了解到,不允许编写 f1 . f2,因为它们打算有两个参数。但是:GHCI 并不抱怨编写它们,我认为它们被“转换”为单参数函数。我仍然对签名的阅读一无所知:那么,a -> (a -> a) -> a -> a 的(人类)阅读是什么,我可以从这个阅读中推断出论点的应用吗?
    猜你喜欢
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    相关资源
    最近更新 更多