【发布时间】:2014-04-16 08:14:01
【问题描述】:
情况
我有函数 f,我想用函数 g 扩充它,从而生成名为 h 的函数。
定义
“增强”,在一般情况中,我的意思是:转换函数f 的输入(一个或多个参数)或输出(返回值)。
“增强”,在特定情况中,(特定于我目前的情况)我的意思是:仅转换函数f 的输出(返回值),同时保持所有参数不变。
通过“透明”,在“增强”的上下文中,(一般情况和特定情况)我的意思是:耦合g的尽可能松散地实现f 的实现。
具体情况
在我目前的情况下,这是我需要做的:
h a b c = g $ f a b c
我有兴趣将其重写为如下内容:
h = g . f -- Doesn't type-check.
因为从h 和g 的角度来看,f 采用什么参数并不重要,它们只关心返回值,因此以任何方式提及参数都是紧密耦合的。例如,如果将来f 的参数计数发生变化,h 也将需要更改。
到目前为止
我在#haskell IRC 频道上询问了 lambdabot:@pl h a b c = g $ f a b c,我得到了回复:
h = ((g .) .) . f
这仍然不够好,因为(.) 的数量取决于f 的参数数量。
一般情况
我在这个方向上没有做太多研究,但#haskell 上的erisco 将我指向http://matt.immute.net/content/pointless-fun,这向我暗示一般情况的解决方案是可能的。
到目前为止
使用上篇文章中 Luke Palmer 定义的函数,这似乎等同于我们目前所讨论的内容:
h = f $. id ~> id ~> id ~> g
但是,如果我们想转换 f 的返回值,这个方法似乎也很遗憾地依赖于 f 的参数数量——就像以前的方法一样。
工作示例
例如,在 JavaScript 中,可以像这样实现透明增强:
function h () { return g(f.apply(this, arguments)) }
问题
如何在 Haskell 中“透明地增强”函数?
我主要对特定情况感兴趣,但如果知道如何处理一般情况也很好。
【问题讨论】:
-
假设有可能,那么
h的类型应该是什么?这不应该取决于f的类型吗? -
@LeeDuhem 是的,
h的类型将基于f,除了返回值,它将是@987654349 返回值的类型@. -
@LeeDuhem 像这样:
f :: ... -> a {- we don't care/don't know what is in '...' -}、g :: a -> b和h :: ... -> b {- '...' is the same as for f -} -
h需要一个类型,以便...成为某种东西。虽然你可以用类型变量来表达“我不关心具体类型是什么”的意思,但据我所知,在 Haskell 中没有办法表达我不关心有多少参数。跨度> -
你在一个多参数函数的类型中明确了隐式括号,然后尝试应用你的省略号,你会明白为什么它这么难。 (省略号不捕获右括号。)例如
a -> b -> c -> d ~ a -> (b -> (c -> d)).
标签: haskell