Haskell: 'do [1,2,3]; ["привет"]'разъяснение поведения

Поэтому я пытаюсь понять, как именно Хаскель do нотация работает. Я понимаю, что он используется вместе с монадами и что он в основном расширяется (так как на самом деле это синтаксический сахар) в анонимные функции, связанные с любой связью (>>=) или потом (>>), как показано здесь https://en.wikibooks.org/wiki/Haskell/Syntactic_sugar.

Однако мой вопрос, почему следующая команда

Prelude> do [1, 2, 3]; "hello"

возвращается

"hellohellohello"

Я знаю, что массивы на самом деле являются монадами (а строки - массивами символов), но я не вижу, как это приводит к описанному выше поведению.

2 ответа

Решение
do [1, 2, 3]; "hello"

Desugars для

[1, 2, 3] >> "hello"

который так же, как

[1, 2, 3] >>= (\_ -> "hello")

который так же, как

concatMap (\_ -> "hello") [1, 2, 3]

который так же, как

concat (map (\_ -> "hello") [1, 2, 3])

который так же, как

concat [(\_ -> "hello") 1, (\_ -> "hello") 2, (\_ -> "hello") 3])

который так же, как

concat ["hello","hello","hello"]

который так же, как

"hellohellohello"

Чтобы дополнить ответ Иоахима Брейтнера, рассмотрим это с другой стороны:

do [1, 2, 3]
   "hello"

является

do a <- [1, 2, 3]
   b <- "hello"
   return b

является

do a <- [1, 2, 3]
   do b <- "hello"
      do return b

является

[b | a <- [1,2,3], b <- "hello"]

такой же, как псевдокод

for a in (a list of Nums) [1, 2, 3]:
   -- here we have `a` (a Num)
   for b in (a list of Chars) "hello":
      -- here we have that same `a` (a Num), 
      -- and `b` (which is a Char)
      emit b       -- whatever "emit" means

Конечно, списочные выражения для списков (не "массивов") вещей (какими бы они ни были, скажем, Nums, Chars и т. Д.) Десугаром в одно и то же concatMap- используя код; но иногда легче обрабатывать их мысленно, как есть, или как спецификацию для некоторых вложенных циклов.

На самом деле кажется, что doпримечание могло бы быть легко for-отношения в первую очередь.

Другие вопросы по тегам