'Ссылка' на функции класса типов - PullRequest
0 голосов
/ 14 февраля 2019

Я новичок, и я пытаюсь использовать 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,Состояние и т. Д.) >>= функция

1 Ответ

0 голосов
/ 15 февраля 2019

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

Вы не ошиблись, ожидая, что написание bind' без подписи должно "просто работать".Однако иногда компилятору требуется небольшая помощь.Короче говоря, из-за MonomorphismRestriction 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 отключить MonomorphismRestriction:

{-# LANGUAGE NoMonomorphismRestriction #-}

import Debug.Trace

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

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

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

...