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