'Ссылка' на функции класса типов

Я новичок, и я пытаюсь использовать Hoed для отслеживания оценок Haskell, потому что, возможно, это еще больше поможет моему процессу обучения.

Я видел в их примерах код, подобный этому

isEven :: Int -> Bool
isEven = observe "isEven" isEven'
isEven' n = mod2 n == 0

Я думал, как я мог observe для того, чтобы отследить экземпляр определенной функции, такой как >>= например.

Я написал что-то вроде

bind' = observe "bind'" (>>=)

и конечно у меня ошибка

* Ambiguous type variable 'm0' arising from a use of '>>='
  prevents the constraint '(Monad m0)' from being solved.
  Relevant bindings include
    bind' :: m0 a0 -> (a0 -> m0 b0) -> m0 b0 (bound at my.hs:46:1)
  Probable fix: use a type annotation to specify what 'm0' should be.
  These potential instances exist:
  ...

Должен ли я / как я могу использовать аннотацию типа, чтобы указать, какие Monad экземпляры (например, Reader, State и т. д.) >>= функция

1 ответ

Решение

Похоже, вы нашли печально известный MonomorphismRestriction, Больше информации Ссылки прекрасно объясняют, что такое ограничение MonomorphismRestriction и как оно работает.

Вы не ошиблись, ожидая, что написание bind' без подписи должен "просто работать". Однако иногда компилятору требуется небольшая помощь. Короче говоря, из-за ограничения Monomorphism GHC пытается получить номинально полиморфную сигнатуру bind' :: Monad m => m a -> (a -> m b) -> m bи сделать его менее полиморфным путем создания экземпляров некоторых переменных типа.

В вашем случае, похоже, что компилятор хочет сделать bind' работать только для одного конкретного Monad m, Без вашего реального кода я не могу сказать наверняка, но рассмотрим этот пример:

import Debug.Trace

main :: IO ()
main = (>>=) (return "hello") print

bind' = trace "bind" (>>=)

Компилятор выдает ошибку, похожую на вашу: Ambiguous type variable m0

Однако, если вы используете bind':

import Debug.Trace

main :: IO ()
main = bind' (return "hello") print

bind' = trace "bind" (>>=)

Нет ошибок! Это потому, что GHC делает вывод, что m должно быть IO поскольку bind' используется в IO монада.

В качестве альтернативы вы можете указать GHC отключить ограничение Monomorphism:

{-# LANGUAGE NoMonomorphismRestriction #-}

import Debug.Trace

main :: IO ()
main = (>>=) (return "hello") print

bind' = trace "bind" (>>=)

и компилируется просто отлично!

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