Haskell - перевод с синтаксического сахара - PullRequest
1 голос
/ 08 февраля 2012

задача состоит в том, чтобы перевести это

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) для возврата, он компилируется, но, очевидно, он больше не дает ожидаемого результата. Как мне вернуть "ничто" в других ветках?

Если я добавлю в качестве возвращаемых значений ((), (), ()), компилятор получит «Нет экземпляра для (Num [a]), возникающего из литерала '1'"

Ответы [ 2 ]

8 голосов
/ 08 февраля 2012

Вместо return (), то есть [()], вы должны создать пустой список, поэтому else [] или, с общей реализацией guard else mzero.

Ветвь успеха создает список троек [(Int,Int,Int)] (или Integer, или другого типа Num), поэтому ветви с ошибками должны выдавать то же самое. Поскольку сбой означает, что тройка не найдена, они должны создать пустой список.

Обратите внимание, что в монаде [], return x - это просто [x], а mzero (из MonadPlus) совпадает с fail whatever, а именно [].

5 голосов
/ 08 февраля 2012

guard на самом деле не является синтаксическим сахаром.Это функция из Control.Monad.

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

В случае списков mzero равно [].Подробнее здесь: http://en.wikibooks.org/wiki/Haskell/MonadPlus

...