Позволяет превратить это в эквивалентные вызовы к >>=
:
["test"] >>= (\first ->
doSomething [1] >>= (\_ -> return first))
Компилятор всегда делает это внутренне с do
. Два способа написания - это точно то же самое.
Теперь >>=
для []
такой же, как concatMap
с его аргументами перевернута, так что давайте идти вперед и сделать это преобразование, а также (и применить определение return x = [x]
) и уменьшить:
concatMap (\first -> concatMap (\_ -> [first]) (doSomething [1])) ["test"]
concatMap (\first -> concatMap (\_ -> [first]) ([1] ++ [1])) ["test"]
concatMap (\first -> concatMap (\_ -> [first]) [1, 1]) ["test"]
concatMap (\first -> concat [[first], [first]]) ["test"]
concatMap (\first -> [first, first]) ["test"]
concat [["test"], ["test"]]
["test", "test"]
Наглядно []
Монаду можно представить как представляющую собой «недетерминированное» вычисление (т. Е. Вычисление, которое может принимать один из нескольких возможных возможных результатов). Когда вы комбинируете два недетерминированных вычисления таким образом, число результатов умножается. Это связано с различными «путями», которые можно взять, по одному для каждой возможности в каждой ветви.
Для справки, здесь является преобразование между do
нотации и >>=
и >>
вызовов (обратите внимание, что m1 >> m2
всегда должна быть эквивалентна m1 >>= (\_ -> m2)
):
do x <- m1 m1 >>= (\x ->
m2 x m2 x
... ...)
do m1 m1
m2 >> m2
do x x
Вы должны прочитать список монады. Также имейте в виду, что необязательное выражение в блоке do семантически такое же, как привязка к значению throwaway, например '_ <- doSomething [1]' –
Ответчикам: как новичок, только что просвещенный эквивалентом вы показали, я был бы на 200% счастливее, если бы был указатель на то, почему и как они эквивалентны. Хорошие ответы и комментарий. – Yosh
Обозначение @Yosh 'do' эквивалентно вызовам' >> = ', потому что именно так оно и определено. Перед компиляцией кода компилятор фактически изменяет все обозначения 'do' на' >> = 'вызовы. Итак, 'do' действительно просто удобная стенограмма для вызова' >> = '(и' >> '). 'do {v <- m1; m2 v} 'превращается в' m1 >> = (\ v -> m2 v) 'и' do {m1; m2} 'превращается в' m1 >> m2' (также 'do x' всегда совпадает с' x', для любого одиночного значения или одной связанной переменной 'x'). Я добавил эту информацию к моему ответу. –