Haskell - 从句法糖翻译

时间:2012-02-08 15:52:05

标签: haskell syntactic-sugar

任务是翻译这个

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”?

如果我输入((),(),())作为返回值,编译器会得到一个“没有实例(Num [a])来自文字'1'”

2 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:5)

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

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

如果列表mzero[]。在此处阅读更多内容:http://en.wikibooks.org/wiki/Haskell/MonadPlus