Какова оценка типа MonadPlus по умолчанию в Haskell?

У меня есть следующий код:

import Control.Monad

coin :: MonadPlus m => m Int
coin = return 0 `mplus` return 1

Если я оцениваю coin :: Maybe Int в интерпретаторе, он выводит Just 0. Это нормально из-за реализации Maybe как экземпляра MonadPlus.

Если я оцениваю coin :: [Int] в интерпретаторе, он печатает [0, 1], потому что реализация mplus в списке — это append.

Но если я оцениваю coin без каких-либо декораторов типов, он печатает 0. Почему? Какой тип интерпретатор "преобразует" coin для его оценки?

Этот код взят с: http://homes.sice.indiana.edu/ccshan/rational/S0956796811000189a.pdf


person ManuelVS    schedule 28.10.2018    source источник


Ответы (2)


Да, это не очень хорошо задокументированный уголок ghci. Когда вы вводите выражение в ghci, он использует тип выражения, чтобы решить, что делать:

  1. IO (): Запустить действие, больше ничего не делать.
  2. Show a => IO a: выполнить действие и print получить результат.
  3. любое другое IO a: запустить действие, больше ничего не делать.
  4. что-нибудь еще: оберните все выражение print.

Как он решает, какой из этих типов имеет вещь? Легко: он пытается унифицировать тип вашего выражения, в котором каждая из вышеперечисленных сигнатур по очереди решает все возникающие ограничения. (Для знатоков: это в дополнение к расширенным правилам по умолчанию! Это объясняет, почему кажется, что по умолчанию используется m, хотя ни стандартные правила по умолчанию, ни расширенные правила по умолчанию не говорят, какое значение по умолчанию использовать. .)

Итак, поскольку ваше выражение не объединяется с IO (), но объединяется с Show a => IO a, ghci находит m ~ IOa ~ Int) во время объединения, обнаруживает, что существует экземпляр MonadPlus IOShow Int) для устранения ограничений, запускает ваше действие и печатает результат.

person Daniel Wagner    schedule 28.10.2018

GHCi (но не GHC в целом) при отсутствии сигнатуры, указывающей иное, будет специализировать конструкторы полиморфных типов до IO, когда это возможно. IO действия в приглашении, в свою очередь, выполняются, и их результаты монадически привязаны к переменной it, которая затем печатается (т.е. do { it <- action; print it }) до тех пор, пока существует экземпляр Show для типа результата (ср. ответ Даниэля Вагнера). Дополнительные сведения см. в действия ввода-вывода в командной строке и Переменные it в Руководстве пользователя.

В вашем конкретном случае бывает, что существует экземпляр MonadPlus для IO. Вы получаете return 0, потому что mplus для IO выполняет второе действие только в том случае, если первое выдает исключение. Одна демонстрация:

GHCi> readLn `mplus` readLn :: IO Integer
0
0
GHCi> readLn `mplus` readLn :: IO Integer
foo
1
1
GHCi> readLn `mplus` readLn :: IO Integer
foo
bar
*** Exception: user error (Prelude.readIO: no parse)
person duplode    schedule 28.10.2018