haskell - Haskell 中 (<*>) 的默认定义是如何工作的?

标签 haskell functional-programming

在 Haskell 中,(<*>) 的默认实现Control.Applicative 中的运算符(它将函数 a->b 的应用程序应用于 a 的应用程序,从而产生 b 的应用程序)。

(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id

我根本无法理解它是如何工作的。

liftA2类型为 liftA2 :: (a -> b -> c) -> f a -> f b -> f c ,这意味着它需要一个二元函数,即 id不是。根据我的理解,这意味着 id在某种程度上被解释为某种更复杂的类型 - 但我不确定它是哪个或如何使这个定义起作用。如果有人可以解释一下 id 是什么类型解释为( a 定义中的 id :: a -> a 代表什么类型),并详细说明它如何产生一个函数,该函数采用函数的应用程序和值的应用程序并应用它们,我将非常感激。

最佳答案

假设 id 的类型是 d -> d ,所以我们所有的类型变量都有不同的名称。现在我们引入两个新的类型变量et并说d = e -> t 。这使得类型为 id :

id :: (e -> t) -> e -> t

现在这符合 liftA2 第一个参数的类型与 a = e -> t , b = ec = t 。因此,通过这些分配, liftA2 的类型变成:

liftA2 :: ((e -> t) -> e -> t) -> f (e -> t) -> f e -> f t

如果我们应用第一个参数,剩余的类型将变为 f (e -> t) -> f e -> f t ,这正是 <*> 的类型(模数重命名)。

关于haskell - Haskell 中 (<*>) 的默认定义是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47065766/

相关文章:

haskell - 在emacs中编码Haskell时找不到"Stack"

haskell - cabal 更新: Local and remote files match

haskell - 将两个关联列表与正在运行的累加器合并

javascript - 我无法理解 Y-Combinator,所以我尝试实现它并最终得到了一些更短的东西,但它起作用了。这怎么可能?

Java 8 : functional way to write sort, 同时过滤和计数

data-structures - 镜头、fclabels、数据访问器——哪个库用于结构访问和变异更好

解释的Haskell数据

javascript - 按类型对集合值求和并分配给复制对象上的新属性

recursion - SML 中的递归匿名函数

haskell - 有没有办法在 Haskell 中记住一个值?