【问题标题】:Haskell - Translating from syntactic sugarHaskell - 从语法糖翻译
【发布时间】:2012-02-08 15:52:04
【问题描述】:

翻译这个的任务是

f = do
    c <- [1 .. 200]
    b <- [1 .. 200]
    guard (c >= b)
    a <- [1 .. 200]
    guard (a >= b && (c^2 - a^2 == b^2))
    return (a,b, c)

变成不含糖的版本。

我想我已经解决了大部分问题,但我被困在中间,有一个问题需要解决,然后才能继续。到目前为止,我有:

f = [1 .. 200] >>= \c ->
    [1 .. 200] >>= \b ->
    if (c >= b) 
        then [1 .. 200] >>= \a -> if (a >= b && (c^2 - a^2 == b^2)) 
                                      then return(a,b,c)
                                      else return ()
        else return ()

不编译。当我输入 (a,b,c) 作为返回值时,它会编译,但显然它不再给出预期的结果。如何在 else 分支中返回“nothing”?

如果我将 ((),(),()) 作为返回值,编译器会得到一个“No instance for (Num [a]) from the literal '1'”

【问题讨论】:

  • 顺便说一下,[1 .. 200] 可以被认为是enumFromTo 1 200 的“语法糖”。
  • 有不止一种可能的翻译。例如,可以将其重写为列表推导式,并通过一种避免连接的方案进行翻译。

标签: haskell syntactic-sugar


【解决方案1】:

您必须生成一个空列表,而不是return (),即[()],因此else [] 或通用guard 实现else mzero

成功分支产生一个三元组列表,[(Int,Int,Int)](或Integer,或另一个Num 类型),因此失败分支必须产生相同的结果。由于失败意味着没有找到三元组,因此它们将生成一个空列表。

请注意,在[] monad 中,return x 只是[x],而mzero(来自MonadPlus)与fail whatever 相同,即[]

【讨论】:

  • 这很快。它解决了我的问题。非常感谢你。 :)
  • guard 使用mzero,而不是fail
【解决方案2】:

guard 实际上并不是语法糖。这是来自Control.Monad 的函数。

guard :: MonadPlus m => Bool -> m ()
guard True  = return ()
guard False = mzero

如果列表mzero[]。在这里阅读更多:http://en.wikibooks.org/wiki/Haskell/MonadPlus

【讨论】:

  • 我在正确放置语法时遇到了问题,因此决定替换 guard 命令。它现在按应有的方式工作。但该链接对后续任务很有帮助。谢谢。 :)
猜你喜欢
  • 2015-05-24
  • 2020-07-24
  • 1970-01-01
  • 2015-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-23
  • 2021-10-28
相关资源
最近更新 更多