Why doesn't the GHC type test this function using polymorphism and existential types?

I have a Haskell code that will not compile (with GHC 8.0.2). I think I understand the main problem, but I would like to understand it better in order to avoid this in the future.

My library looks something like this:

{-# language TypeFamilyDependencies #-}
{-# language GADTs #-}
{-# language RankNTypes #-}

module Lib where

type Key = Int

class Handle m where
    type Connection m = c | c -> m
    withConnection :: Connection m -> m a -> IO a

class (Handle m) => Data m where
    getKeyVal :: Key -> m String

data SomeConn where
    SomeConn :: (Data m) => Connection m -> SomeConn

useConnection :: SomeConn -> (forall m. Data m => m String) -> IO String
useConnection (SomeConn c) action = withConnection c action

The idea is what Data mconstitutes a class of monads, similar ReaderT (Connection m) IO. I hope to write common functions using methods of this type, and an instance of the exact method is determined by the type of connection enclosed in SomeConn(which is selected at runtime).

Now the following code

getKeyValWith :: SomeConn -> Key -> IO String
getKeyValWith c = (useConnection c). getKeyVal

gives me the GHC 8.0.2 error:

• Couldn't match type ‘m0 String’
                 withforall (m :: * -> *). Data m => m String
  Expected type: m0 String -> IO String
    Actual type: (forall (m :: * -> *). Data m => m String)
                 -> IO StringIn the first argument of ‘(.)’, namely ‘useConnection c’
  In the expression: useConnection c . getKeyVal
  In an equation for ‘getKeyValWith’:
      getKeyValWith c = useConnection c . getKeyVal

Oddly enough, the following works just fine:

getKeyValWith c k = useConnection c (getKeyVal k)

Less unexpectedly, also:

getKeyValWith (SomeConn c) = withConnection c . getKeyVal

, GHC , ? , GHC , , ? , , , Haskell ( "/typeclass anti-pattern" ).

Edit:

, , getKeyVal :: Key -> (Data m => m String) . ( typechecks), . , , :t GHCI ( -XRankNTypes), Data m =>, . , , GHC . GHC ?

+4
1

.. , f . g , f 2. :

(~.) :: ((∀ m. Data m => m String) -> z) -> (x -> (∀ m. Data m => m String))
          -> x -> z
(~.) f g x = f (g x)

getKeyValWith :: SomeConn -> Key -> IO String
getKeyValWith c = useConnection c ~. getKeyVal

.

(.) :: ∀ c . ((∀ y . c y => y) -> z) -> x -> ((∀ y . c y => y) -> x)
               -> x -> z

, ~. . - c - c y = y~y₀ - , .

( , , . , $. eta-, , , useConnection c . getKeyVal, eta- ...)

Rank-2 GADT, SomeConn, .

+4

Source: https://habr.com/ru/post/1684784/


All Articles