Aad*_*hah 5 haskell category-theory function-composition
考虑以下Haskell代码:
countWhere :: (a -> Bool) -> [a] -> Int
countWhere predicate xs = length . filter predicate $ xs
Run Code Online (Sandbox Code Playgroud)
在JavaScript中,这将写成如下:
function countWhere(predicate, xs) {
return xs.filter(predicate).length;
}
Run Code Online (Sandbox Code Playgroud)
如您所见,函数组合与JavaScript中的链接方法非常相似.我真的很喜欢链接方法从左到右读取的方式.在Haskell中,我可以使用>>>函数from Control.Arrow和reverse函数应用程序执行类似的操作,如下所示:
import Control.Arrow
($>) :: a -> (a -> b) -> b
($>) = flip ($)
countWhere :: (a -> Bool) -> [a] -> Int
countWhere predicate xs = xs $> filter predicate >>> length
Run Code Online (Sandbox Code Playgroud)
现在我想用无点样式编写这个函数.使用函数组合我会写如下:
(.:) :: (b -> c) -> (d -> a -> b) -> d -> a -> c
(.:) = (.) (.) (.)
countWhere :: (a -> Bool) -> [a] -> Int
countWhere = length .: filter
Run Code Online (Sandbox Code Playgroud)
但是我想使用反向函数组合以无点样式编写此函数,如下所示:
(.:) :: (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
Run Code Online (Sandbox Code Playgroud)
我的抱怨是我必须:.根据功能组成而不是反向功能组合来定义功能.那是:
(:.) = flip $ (.) (.) (.)
-- instead of
(:.) = (>>>) (>>>) (>>>)
Run Code Online (Sandbox Code Playgroud)
当然(>>>) (>>>) (>>>)是错误的类型.这不是我要找的功能.
功能组合物的美妙之处在于它可以自身组成以形成如上所述的"高阶功能组合物".因此,虽然它的类型签名直观地向后,它实际上是向前,这解释了为什么f . g = \x -> f (g x)而不是f . g = \x -> g (f x).
这让我想到了我的实际问题:有没有办法用反向函数组合(即>>>)来定义"高阶反向函数组合" 而不是flip相应的"高阶函数组合"?
我正在寻找一个源于类别理论或其他数学分支的答案.
所以这是一个伪无点答案
(.:.) :: (a -> b -> c) -> (c -> d) -> a -> b -> d
f .:. g = (,) f >>> app >>> (>>> g)
Run Code Online (Sandbox Code Playgroud)
这依赖于类别理论中所谓的"指数".Expontentials基本上提供两个功能
curry :: ((a, b) -> c, a) -> c^b
eval :: (c^b, b) -> c
Run Code Online (Sandbox Code Playgroud)
这或多或少是curry和的一般版本uncurry ($).
这可以转换为pointfree(by pointfree)
(.:.) = (. flip (>>>)) . (>>>) . (>>> app) . (,)
(.:.) = (,) >>> fmap app >>> (>>>) >>> ((<<<) >>>)
Run Code Online (Sandbox Code Playgroud)
这很好,很可怕.另一种选择是使用curry和uncurry.Curry和uncurry必不可少见证指数与箭之间的同构性:Hom((a, b), c) ~~ Hom(a, c^b).in Hask.
(.:.) = uncurry >>> (>>>) >>> (>>>curry)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1481 次 |
| 最近记录: |