【发布时间】:2013-05-25 09:39:19
【问题描述】:
我想知道 Haskell 是否跟踪天气一个函数是一个函数组合,即我是否可以定义一个做类似事情的函数?:
compositionSplit f.g = (f,g)
【问题讨论】:
标签: haskell function-composition
我想知道 Haskell 是否跟踪天气一个函数是一个函数组合,即我是否可以定义一个做类似事情的函数?:
compositionSplit f.g = (f,g)
【问题讨论】:
标签: haskell function-composition
它可以。在严格解释的非编译实现中,您可以将函数表示为
data Function = F Source | Compo Function Function
然后你只需定义
compositionSplit (Compo f g) = Just (f,g)
compositionSplit _ = Nothing
这样的实现会将函数相等(w.r.t. 引用透明度)视为intensional,而不是extensional 相等。由于语言本身并没有说明函数相等 AFAIK,这不应该影响任何事情(可能除了性能)。
在已编译的实现中,这也可以实现,例如通过维护内存中每个对象的出处。
AndrewC 给出了一个成功的反驳论点:对于两个值 a=f.(g.h) 和 b=(f.g).h,如果我们想将它们视为相等的值 - 我们通常在 Haskell 中这样做 - fst.unJust.deCompo 将产生两个不同的结果,打破参照透明度。所以它不能成为纯 FP 范式的一部分。在这两种情况下,它必须返回我们可以合理地认为是相等值的东西,并且我们无法在不破坏纯度的情况下将其拆开。也许这样的事情可能存在于一些不纯的单子中,但遗憾的是,这不是 OP 所要求的。 :) 所以这个答案是错误的。
【讨论】:
不,这不可能。
例如,
f1 = (+ 1) . (+ 1) :: Int -> Int
与
功能相同f2 = subtract 1 . (+ 3) :: Int -> Int
并且引用透明性要求equals可以替代equals,所以如果compositionSplit是可能的,它会
f1 和f2 生成相同的结果,因为这是相同的功能,但compositionSplit f1 = ((+ 1), (+1)) 和 compositionSplit f2 = (subtract 1, (+ 3)) 将是 compositionSplit 规范所必需的。【讨论】:
f1和f2是同一个函数,所以不能用任何函数来区分。
x = y 时,也就是f x = f y。观察f1 和f2 相等,因此compositionSplit f1 应该等于compositionSplit f2,但事实并非如此!
(\x.x+2) 和 (\x.x+1+1) 只是 extensionally equal functions。在具有内涵平等的语言中,我们可以区分两者。 (只需携带源代码和简化/编译步骤,以及内存中已编译的函数对象 -- “provenance”)。
(.) 和 id 成为一个幺半群,即 f.(g.h) = (f.g).h 和 id.f = f 时,我的观点也许是最好的。你不能有参照透明,这个幺半群和分解运算符。如果你没有这个,你就不是在做纯粹的函数式编程。这不是不可能的,只是不是f.p..