Следующий тест взял меня врасплохHaskell - пусть связывание выбирает неверный экземпляр
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Test where
class Type t where
encodeToField :: t -> String
class Rec r where
encodeToRec :: r -> String
data X a b = X a b
instance (Type t) => Rec t where
encodeToRec = encodeToField
instance (Type t, Rec r) => Rec (X t r) where
encodeToRec (X t r) =
let x = encodeToField t
y = encodeToRec r
in x ++ y
GHC терпит неудачу на этом с
Test.hs:19:17
Could not deduce (Type r) arising from a use of `encodeToRec'
from the context (Type t, Rec r)
По какой-то причине GHC хочет использовать экземпляр Type t => Rec t
в y = encodeToRec r
, вместо просто беря Rec r
из контекста объявления экземпляра.
Если избежать Выпускаемое связывания и вместо того, чтобы писать
instance (Type t, Rec r) => Rec (X t r) where
encodeToRec (X t r) = encodeToRec t ++ encodeToRec r
компилирует.
Является ли это ошибкой в ghc или должно ли это поведение ожидаться из-за используемых языковых расширений?
Пока не понял этого, но я обнаружил, что более простая программа создает проблему: если вы определяете 'newtype Foo a = Foo a', тогда определите экземпляр' Rec r => Rec (Foo r) ', с' encodeToRec (Foo r) = x, где x = encodeToRec r', он дает ту же ошибку. Хотя экземпляр вообще не относится к типу. Странно ... –
@ AdamR.Nelson Спасибо за упрощение. Мне не хотелось работать, надеюсь, что OP не слишком длинный :-) –
Это кажется странным. Выражение '++' не должно быть typecheck, так как 't' не имеет ограничения' Rec'? – Sibi