Type abstraction in GHC Haskell

荒凉一梦 提交于 2019-12-30 09:05:05

问题


I'd love to get the following example to type-check:

{-# 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

I get it that it's probably not possible to infer and check gs type (even though in this specific case it's obvious because it's just a partial application): Secret is not injective and there's no way to tell the compiler which Functor instance it should expect. Consequently, it fails with the following error message:

    • 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
    |     ^^^

So some guidance by the programmer is needed and it would readily be accepted if I could write g like this:

g :: (forall f. Functor f => Secret f) -> Int
g h = f 4 (\\f -> h @f)

Where \\ is hypothetical syntax for System Fw's big lambda, i.e. type abstraction. I can emulate this with ugly Proxys, but is there some other GHC Haskell feature that let's me write something like this?


回答1:


This might be a GHC bug. I can not see how this GHC behavior makes any sense.

This issue has nothing to do with type families, but it seems to arise from ambiguous types and typeclass constraints.

Here is a MCVE for the same issue.

{-# 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

It seems that f can not be called with any argument that actually exploits the constraint.




回答2:


This is by design. It seems there is no way around using Proxys for now: https://ghc.haskell.org/trac/ghc/ticket/15119.

Edit Jul 2019: There's now a GHC proposal for this!



来源:https://stackoverflow.com/questions/50159349/type-abstraction-in-ghc-haskell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!