Хаскель Монадические формы - PullRequest
2 голосов
/ 06 июля 2011

Простой вопрос: учитывая определения (из Haskell SOE)

   do x — el; el\ ...; en 
    => el »= \x — do e2\ ...; en 

и:

do let decllist; el\...; en 
=> let decllist in do e2\ ...; en 

кажется, что эти две конструкции одинаковы:

do let x = e1
   e2

и

do x <- e1
   e2

оба оценивают e1, связывают его с e2, а затем оценивают e2.

Да?

Ответы [ 4 ]

4 голосов
/ 06 июля 2011

Давайте сделаем простой пример в монаде Maybe:

foo = do
        let x = Just 1
        return x

и

bar = do
        x <- Just 1
        return x

Обесценивая оба, мы получаем

foo = let x = Just 1 in return x    -- do notation desugaring
    = return (Just 1)               -- let
    = Just (Just 1)                 -- definition of return for the Maybe monad

bar = let ok x = return x in Just 1 >>= ok   -- do notation desugaring
    = let ok x = return x in ok 1   -- definition of >>= for the Maybe monad
    = return 1                      -- definiton of ok
    = Just 1                        -- definition of return for the Maybe monad

Для справки я использую перевод из раздела 3.14 отчета Haskell 2010 .

3 голосов
/ 06 июля 2011

Нет, они не одинаковы.Например,

do let x = getLine
   print x

переводится в

let x = getLine in print x

, это ошибка типа, так как x будет иметь тип IO String.Мы просим напечатать само вычисление, а не его результат.


do x <- getLine
   print x

преобразуется в

getLine >>= \x -> print x

Здесь x связывается как результат вычисления иего тип - String, поэтому этот тип проверяет.


В примечании do let просто привязывает значения к именам, как всегда, в то время как <- используется для выполнения монадическогосвязывание, которое связывает имя с результатом вычисления.

1 голос
/ 06 июля 2011

Если e1 - это вычисление типа Monad m => m a, то let x = e1 и x <- e1 означают несколько разные вещи.

В версии let, когда вы используете x ввыражение do, вы имеете дело со значением типа Monad m => m a.

В другой версии, когда вы используете x в выражении do, вы имеете дело со значением типа a(поскольку do-нотация неявно обрабатывает отображение над монадой).

Например:

e :: IO Int
f :: Int -> Int

-- the following will result in a type error, since f operates on `Int`, not `IO Int`:
g = do let x = e
       return $ f x

-- the following will work:
g' = do x <- e
        return $ f x
0 голосов
/ 06 июля 2011

Нет. x <- e1 переводится в e1 >>= \x ->, неполное выражение; выражение let является просто нормальным let. Или вы спрашиваете, если let и (>>=) это одно и то же? Это не так: (>>=) подвергает объект, завернутый монадой, функции, которая должна производить что-то, завернутый в монаду. Другими словами, с x <- e1 тип e1 должен быть IO a для некоторых a, но с типом let x = e1 e1 просто a; в обоих случаях тип x будет a.

...