【问题标题】:Is it possible write this code without using do notation?是否可以在不使用 do 表示法的情况下编写此代码?
【发布时间】:2019-02-12 04:12:26
【问题描述】:

我有一些功能

bar :: MyType -> MyType -> [MyType]

我想要另一个功能:

foo :: [MyType] -> [MyType]
foo xs = do x <- xs
            y <- xs
            bar x y

是否可以在不使用do 符号的情况下编写foo?我在想liftA2 之类的东西,但那行不通。

【问题讨论】:

  • 所有的do符号都可以用&gt;&gt;=return重写,为此甚至还有一个特殊的使用函数。
  • 对,您在技术上是正确的。我真正的意思是,如果我可以使用Control.ApplicativeControl.Monad 中的函数以某种自然的方式重写它,并且没有lambda。由&gt;&gt;= 重写通常需要许多 lambda。
  • "正在考虑类似 liftA2 的东西,但那行不通。"为什么不呢?
  • @M.Aroosi:注意bar 在这里是一元类型,它不是 return (bar x y),而只是bar x y
  • 对,你可以使用liftA2join tho。

标签: haskell linked-list monads do-notation


【解决方案1】:

您也可以使用以下模式为 bar 提供不同的参数:

Arity 2

-- bar :: [MType] -> [MType]
foo :: [MType] -> [MType]
foo xs = join $ bar <$> xs <*> xs

Arity 3

-- bar :: [MType] -> [MType] -> [MType]
foo :: [MType] -> [MType]
foo xs = join $ bar <$> xs <*> xs <*> xs

等等。

我喜欢这个,因为它比硬编码的liftA2 更容易扩展。

【讨论】:

    【解决方案2】:

    我们可以使用来自do-blocks的算法转换,如Haskell report中所述:

    foo :: [MType] -> [MType]
    foo xs = xs >>= \x -> xs >>= \y -> bar x y
    

    但我们可以通过省略 y 变量来减少 lambda 表达式的数量:

    foo :: [MType] -> [MType]
    foo xs = xs >>= \x -> xs >>= bar x
    

    我们也可以省略x变量,将\x -&gt; xs &gt;&gt;= bar x写成(xs &gt;&gt;=) . bar

    foo :: [MType] -> [MType]
    foo xs = xs >>= ((xs >>=) . bar)
    

    或者像@M.Aroosi说的,我们可以使用join :: Monad m =&gt; m (m a) -&gt; m aliftA2 :: Applicative f =&gt; (a -&gt; b -&gt; c) -&gt; f a -&gt; f b -&gt; f c的组合:

    foo :: [MType] -> [MType]
    foo xs = join (liftA2 bar xs xs)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      • 2017-01-05
      • 1970-01-01
      • 2011-10-26
      • 2021-11-29
      • 2021-06-08
      相关资源
      最近更新 更多