Типовая абстракция в GHC Haskell
Я хотел бы получить следующий пример для проверки типа:
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Foo where
f :: Int -> (forall f. Functor f => Secret f) -> Int
f x _ = x
g :: (forall f. Functor f => Secret f) -> Int
g = f 4
type family Secret (f :: * -> *) :: * where
Secret f = Int
Я понимаю, что, вероятно, невозможно сделать вывод и проверить g
тип s (хотя в данном конкретном случае это очевидно, потому что это только частичное приложение): Secret
не является инъективным, и нет никакого способа сказать компилятору Functor
экземпляр этого следует ожидать. Следовательно, происходит сбой со следующим сообщением об ошибке:
• Could not deduce (Functor f0)
from the context: Functor f
bound by a type expected by the context:
forall (f :: * -> *). Functor f => Secret f
at src/Datafix/Description.hs:233:5-7
The type variable ‘f0’ is ambiguous
These potential instances exist:
instance Functor IO -- Defined in ‘GHC.Base’
instance Functor Maybe -- Defined in ‘GHC.Base’
instance Functor ((,) a) -- Defined in ‘GHC.Base’
...plus one other
...plus 9 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: f 4
In an equation for ‘g’: g = f 4
|
233 | g = f 4
| ^^^
Так что какое-то руководство от программиста необходимо, и оно будет с готовностью принято, если я смогу написать g
как это:
g :: (forall f. Functor f => Secret f) -> Int
g h = f 4 (\\f -> h @f)
куда \\
является гипотетическим синтаксисом для большой лямбды System Fw, например, абстракция типа. Я могу подражать этому с уродливым Proxy
s, но есть ли какая-то другая особенность GHC Haskell, которая позволяет мне писать что-то вроде этого?
2 ответа
Это по замыслу. Кажется, нет никакого способа использования Proxy
пока что: https://ghc.haskell.org/trac/ghc/ticket/15119.
Это может быть ошибка GHC. Я не могу видеть, как это поведение GHC имеет какой-либо смысл.
Эта проблема не имеет ничего общего с семействами типов, но кажется, что она возникает из-за неоднозначных типов и ограничений классов типов.
Вот MCVE для той же проблемы.
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
class C a where
getInt :: Int
instance C Char where
getInt = 42
f :: (forall a. C a => Int) -> Bool
f x = even (x @ Char)
g :: (forall a. C a => Int) -> Bool
-- g = f -- fails
-- g h = f h -- fails
-- g h = f getInt -- fails
g _ = f 42 -- OK
Кажется, что f
не может быть вызван с любым аргументом, который фактически использует ограничение.