Я новичок в некоторых из более сложных конструкций типов в Haskell и бездельничал.В настоящее время я застрял, пытаясь получить функцию, которая, по моему мнению, должна работать для проверки типов.
Возьмем следующий код в качестве примера:
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
class X a where
data Y a
z :: Y a -> Int
data D1 = D1
instance X D1 where
data Y D1 = YD1
z _ = 1
data D2 = D2
instance X D2 where
data Y D2 = YD2
z _ = 2
sumZ :: X a => [Y a] -> Int
sumZ = foldl' sumFn 0
where sumFn = flip ((+) . z)
Я хочу a = sumZ [YD1, YD2]
для проверки типов,Это (очевидно) не работает, так как переменная типа a
фиксируется с первым YD1
.
Я понимаю достаточно, чтобы знать, что мне, вероятно, следует использовать типы с более высоким рейтингом, поэтому я попробовал это:
sumZ' :: [(forall a. X a => Y a)] -> Int
sumZ' = foldl' sumFn 0
where sumFn = flip ((+) . z)
Но, когда я пытаюсь скомпилировать его, я сталкиваюсь с "непредсказуемым полиморфизмом":
• Illegal polymorphic type: forall a. X a => Y a
GHC doesn't yet support impredicative polymorphism
• In the type signature: sumZ' :: [(forall a. X a => Y a)] -> Int
|
48 | sumZ' :: [(forall a. X a => Y a)] -> Int
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
После небольшого прочтения я вижу, что традиционное решение заключается в переносезначение в newtype
для обхода неимоверного полиморфизма.
newtype Wrap = Wrap { unWrap :: forall a. X a => Y a }
sumZ'' :: [Wrap] -> Int
sumZ'' = foldl' sumFn 0
where
sumFn acc (Wrap v) = acc + (z v)
К сожалению, это тоже не работает.Компиляция завершается с этим сообщением:
• Ambiguous type variable ‘a0’ arising from a use of ‘z’
prevents the constraint ‘(X a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance X D1
-- Defined at ...
instance X D2
-- Defined at ...
• In the second argument of ‘(+)’, namely ‘(z v)’
In the expression: acc + (z v)
In an equation for ‘sumFn’: sumFn acc (Wrap v) = acc + (z v)
|
64 | sumFn acc (Wrap v) = acc + (z v)
| ^^^
Наконец, мой вопрос (-ы):
- Почему в этом случае не работает стандартная техника «оборачивания»?При проверке типа
v
я вижу, что он имеет тип forall a. X a => Y a
, мне кажется, что он должен работать. - Как я могу заставить
a = sumZ [YD1, YD2]
работать?Я что-то не так делаю?