[英]Writing in pointfree style f x = g x x
我正在学习 Haskell。 很抱歉问了一个非常基本的问题,但我似乎找不到答案。 我有一个由以下定义的函数 f:
f x = g x x
其中 g 是一个已经定义的 2 个参数的函数。 我如何编写这种 pointfree 风格? 编辑:不使用 lambda 表达式。
谢谢
f
可以用Control.Monad.join
编写:
f = join g
函数 monad 上的join
是构造无点表达式时使用的原语之一,因为它不能以无点样式本身定义(它的SKI 演算等价物, 。SII
— Haskell 中的ap id id
— 不输入)
这被称为“W”组合子:
import Control.Monad
import Control.Monad.Instances
import Control.Applicative
f = join g -- = Wg (also, join = (id =<<))
= (g `ap` id) -- \x -> g x (id x) = SgI
= (<*> id) g -- = CSIg
= g =<< id -- \x -> g (id x) x
= id =<< g -- \x -> id (g x) x
S,K,I是一组基本的组合子; B、C、K、W是另一个——你必须在某个地方停下来(重新:你的“无 lambda 表达式”评论) :
_B = (.) -- _B f g x = f (g x) = S(KS)K
_C = flip -- _C f x y = f y x = S(S(K(S(KS)K))S)(KK)
_K = const -- _K x y = x
_W = join -- _W f x = f x x = CSI = SS(KI) = SS(SK)
_S = ap -- _S f g x = f x (g x) = B(B(BW)C)(BB) = B(BW)(BBC)
= (<*>) -- from Control.Applicative
_I = id -- _I x = x = WK = SKK = SKS = SK(...)
{-
Wgx = gxx
= SgIx = CSIgx
= Sg(KIg)x = SS(KI)gx
= gx(Kx(gx)) = gx(SKgx) = Sg(SKg)x = SS(SK)gx
-- _W (,) 5 = (5,5)
-- _S _I _I x = x x = _omega x -- self-application, untypeable
-}
我纯粹是偶然来到这里的,我想提供我的解决方案,因为没有人在这个线程中提到提升,至少没有明确提到。
这是一个解决方案:
f = liftM2 g id id
如何看待它?
g
具有类型a -> a -> b
,即它需要某种类型的两个值(两者的类型相同,否则 OP 给出的f
定义将没有意义),并返回某种类型的另一个值(不一定与参数类型相同);
lift2M g
是的抬起版本g
,它有式(Monad m) => ma -> ma -> mb
:它需要两个一元值,它是每一个在一个所谓的远未指定的上下文中的值,并且给出了回一元值;
当将两个函数传递给liftM2 g
,取决于Monad
的上下文是什么:这些值还没有在那里,但最终会在,当函数接收到它需要的参数时; 换句话说,函数是存储自己未来值的 monad; 因此, lift2M g
输入两个函数(或两个函数的未来值),并返回另一个函数(或它的未来值); 知道这一点,如果将m
更改为(->) r
或r ->
: (r -> a) -> (r -> a) -> (r -> b)
,则其类型与上述相同
我们传递的两个函数都是id
,它承诺它会返回它接收到的相同值;
因此, liftM2 g id id
是一个类型为r -> b
的函数,它将其参数传递给这两个id
,使其保持不变并将其转发给g
。
以类似的方式,可以利用函数是应用函子,并使用以下解决方案:
f = g <$> id <*> id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.