17

我正在学习 Haskell。很抱歉问了一个非常基本的问题,但我似乎找不到答案。我有一个由 f 定义的函数:

f x = g x x

其中 g 是已定义的 2 个参数的函数。我如何编写这种无点风格?编辑:不使用 lambda 表达式。

谢谢

4

3 回答 3

21

f可以写成Control.Monad.join

f = join g

join函数 monad 是构造无点表达式时使用的原语之一,因为它本身不能以无点样式定义(它的SKI 演算等价物,在 Haskell 中SII-ap id id不输入)

于 2012-02-06T23:52:04.230 回答
9

这被称为“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
-}
于 2012-06-15T12:49:59.257 回答
1

我来到这里纯属偶然,我想提供我的解决方案,因为没有人在这个线程中提到提升,至少没有明确地提到。

这是一个解决方案:

f = liftM2 g id id

怎么看?

  • g具有 type a -> a -> b,即它采用某种类型的两个值(两者的类型相同,否则 OP 给出的定义f将没有意义),并返回某种类型的另一个值(不一定与参数的类型相同);

  • lift2M g是的提升版本,g它具有类型(Monad m) => m a -> m a -> m b:它接受两个单子值,每个值都是迄今为止未指定的上下文中的一个值,并返回一个单子值

  • 将两个函数传递给 时liftM2 g,将根据上下文的内容进行掷骰Monad:当函数接收所需的参数时,值尚未存在,但最终会存在;换句话说,函数是存储自己未来值的单子;因此,lift2M g输入两个函数(或,两个函数的未来值),并返回另一个函数(或,它的未来值);m知道这一点,如果您更改为(->) r, 或,则其类型与上述相同r ->(r -> a) -> (r -> a) -> (r -> b)

  • 我们传递的两个函数是 both id,它保证它会返回它收到的相同值;

  • liftM2 g id id因此,它是一个类型函数r -> b,将其参数传递给这两个ids,使其保持不变并将其转发给g.

以类似的方式,可以利用函数是应用函子,并使用以下解决方案:

f = g <$> id <*> id
于 2020-06-06T14:17:26.050 回答