haskell - Haskell 中的反向函数组合

标签 haskell function-composition category-theory

考虑以下 Haskell 代码:

countWhere :: (a -> Bool) -> [a] -> Int
countWhere predicate xs = length . filter predicate $ xs

在 JavaScript 中,这将写成如下:

function countWhere(predicate, xs) {
    return xs.filter(predicate).length;
}

如您所见,函数组合与 JavaScript 中的链接方法非常相似。我真的很喜欢链接方法从左到右读取的方式。在 Haskell 中,我可以使用 >>> 做类似的事情来自 Control.Arrow 的函数以及反向函数应用如下:

import Control.Arrow

($>) :: a -> (a -> b) -> b
($>) = flip ($)

countWhere :: (a -> Bool) -> [a] -> Int
countWhere predicate xs = xs $> filter predicate >>> length

现在我想以点自由风格编写这个函数。使用函数组合我会编写如下:

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

countWhere ::  (a -> Bool) -> [a] -> Int
countWhere = length .: filter

但是我想使用反向函数组合以点自由风格编写此函数,如下所示:

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

(:.) :: (d -> a -> b) -> (b -> c) -> d -> a -> c
(:.) = flip (.:)

countWhere :: (a -> Bool) -> [a] -> Int
countWhere = filter :. length

我的提示是我必须定义 :.函数是函数复合而不是逆函数复合。即:

(:.) = flip $ (.) (.) (.)

-- instead of

(:.) = (>>>) (>>>) (>>>)

当然(>>>) (>>>) (>>>)类型错误。这不是我正在寻找的功能。

函数复合的美妙之处在于它可以与自身复合以形成“高阶函数复合”,如上所示。因此,尽管它的类型签名直观上是向后的,但实际上是向前的,这解释了为什么 f . g = \x -> f (g x)而不是f . g = \x -> g (f x) .

这让我想到了我的实际问题:有没有办法根据反向函数组合(即 >>> )而不是 flip 来定义“高阶反向函数组合”?计算相应的“高阶函数组合”?

我正在寻找一个 Root 于范畴论或其他数学分支的答案。

最佳答案

所以这是一个伪无意义的答案

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

这依赖于范畴论中所谓的“指数”。指数基本上提供两个功能

curry :: ((a, b) -> c, a) -> c^b
eval  :: (c^b, b)         -> c

这或多或少是 curryuncurry ($) 的通用版本。

这可以转换为 pointfree(通过 pointfree)

(.:.) = (. flip (>>>)) . (>>>) . (>>> app) . (,)
(.:.) = (,) >>> fmap app >>> (>>>) >>> ((<<<) >>>)

这很好,但很丑陋。另一种选择是使用 curryuncurry。 Curry 和 uncurry Essential 见证了指数和箭头之间的同构:Hom((a, b), c) ~~ Hom(a, c^b).in Hask。

(.:.) = uncurry >>> (>>>) >>> (>>>curry)

关于haskell - Haskell 中的反向函数组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20158392/

相关文章:

haskell - 我如何用我的一元 Action 惯用地组织我的纯函数

lambda - 如何在 Java 功能接口(interface)中使用 andThen 或类似方法包装函数

haskell - 两个非仿函数可以组成一个仿函数吗?

haskell - 以记录字段名称作为变量的模板 Haskell?

haskell - 在haskell中制作类似网格的数据类型

parsing - 生成解析器,在另一个解析器的输出上运行接收到的解析器并单子(monad)连接结果

haskell - 无论实例如何,都在哪里使用 Haskell 类别组合?

haskell - 我如何概括 Maybe 和 Either 的违约行为?

ios - 使用函数组合时出现编译器错误 : Cannot convert value of type `([Character]) -> String` to expected > argument type `_ -> _`

haskell - Haskell 中的所有类型类都有范畴论类比吗?