【问题标题】:How to rewrite in point-free style with a repeating variable?如何使用重复变量以无点样式重写?
【发布时间】:2018-06-16 06:44:43
【问题描述】:

如何用无点样式重写以下表达式?

p x y = x*x + y

使用 lambda 演算,我做了以下事情:

p = \x -> \y -> (+) ((*) x x) y
  = \x -> (+) ((*) x x) -- here start my problem
  = \x -> ((+) . ((*) x )) x
  ... ?

【问题讨论】:

    标签: haskell pointfree tacit-programming


    【解决方案1】:

    如果你去http://pointfree.io/

    对于

    p x y = x*x + y
    

    它给你

    p = (+) . join (*)
    

    【讨论】:

      【解决方案2】:

      我问lambdabot

      <Iceland_jack> @pl p x y = x*x + y
      <lambdabot> p = (+) . join (*)
      

      join 来自Control.Monad 并且通常具有这种类型

      join :: Monad m => m (m a) -> m a
      

      但是使用instance Monad ((-&gt;) x)(如果我们可以left section types,这可以写成(x -&gt;))我们得到以下类型/定义

      join :: (x -> x -> a) -> (x -> a)
      join f x = f x x
      

      我们让GHCi确认类型:

      >> import Control.Monad
      >> :set -XTypeApplications 
      >> :t join @((->) _)
      join @((->) _) :: (x -> x -> a) -> x -> a
      

      【讨论】:

        【解决方案3】:

        只是为了好玩,你可以使用State monad 来写

        p = (+) . uncurry (*) . runState get
        

        runState get 只是从初始 x 生成一对 (x, x)get 将状态复制到结果中,runState 返回状态和结果。

        uncurry (*) 采用一对值而不是两个单独的值 ((uncurry (*)) (3, 3) == (*) 3 3 == 9)。

        【讨论】:

          【解决方案4】:

          既然您提到了 Lambda 演算,我将建议如何使用 SK 组合器来解决这个问题。 η-reduction 是一个很好的尝试,但正如您所说,当变量被使用两次时,您不能 η-reduce。

          S = λfgx.fx(gx)
          K = λxy.x
          

          重复特征由S编码。您将问题简化为:

          λx.(+)((*)xx)
          

          那么让我们从这里开始吧。 Any lambda term can be algorithmically transformed to a SK term.

          T[λx.(+)((*)xx)]
          = S(T[λx.(+)])(T[λx.(*)xx])        -- rule 6
          = S(K(T[(+)]))(T[λx.(*)xx])        -- rule 3
          = S(K(+))(T[λx.(*)xx])             -- rule 1
          = S(K(+))(S(T[λx.(*)x])(T[λx.x]))  -- rule 6
          = S(K(+))(S(*)(T[λx.x]))           -- η-reduce
          = S(K(+))(S(*)I)                   -- rule 4
          

          在 Haskell 中,S = (&lt;*&gt;)K = pureI = id。因此:

          = (<*>)(pure(+))((<*>)(*)id)
          

          并重写:

          = pure (+) <*> ((*) <*> id)
          

          然后我们可以应用我们知道的其他定义:

          = fmap (+) ((*) <*> id)     -- pure f <*> x = fmap f x
          = fmap (+) (join (*))       -- (<*> id) = join for Monad ((->)a)
          = (+) . join (*)            -- fmap = (.) for Functor ((->)a)
          

          【讨论】:

            猜你喜欢
            • 2018-06-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-04-13
            • 2023-03-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多