Какова стандартная оценка типов MonadPlus в Haskell? - PullRequest
0 голосов
/ 28 октября 2018

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

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

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

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

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

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

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

0 голосов
/ 28 октября 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)
...