inferring type class constraint when using associated type families
I am aware that you can add constraints on associated type families and data families. What this does is enforce the constraints on all instances of your class.
But I can't figure out how to infer these constraints in instance derivation or function declarations . For example, this code fails to type check:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
import Data.Proxy ( Proxy )
class Eq (FooT a) => Foo a where
type FooT a :: *
-- Can't infer it in an instance derivation
data CantInferEq a = CantInferEq (FooT a) deriving Eq
-- Also can't infer it in a function declaration.
-- The Proxy is there to avoid non-injectivity issues.
cantInferEq :: Proxy a -> FooT a -> FooT a -> Bool
cantInferEq _ x y = x == y
the error messages are:
Test.hs:11:52: No instance for (Eq (FooT a)) …
arising from the first field of ‘CantInferEq’ (type ‘FooT a’)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
When deriving the instance for (Eq (CantInferEq a))
Test.hs:16:23: No instance for (Eq (FooT a)) arising from a use of ‘==’ …
In the expression: x == y
In an equation for ‘cantInferEq’: cantInferEq _ x y = x == y
Compilation failed.
What is going on here? Is there a workaround to get my desired behavior?
The crux of the problem is that given just a FooT a
, you have nowhere to pull the Eq
instance dictionary from.
The workaround is to be explicit in your typeclass requirements, thereby having a place where the Eq
dict is passed:
{-# LANGUAGE StandaloneDeriving, UndecidableInstances #-}
data CantInferEq a = CantInferEq (FooT a)
deriving instance (Eq (FooT a)) => Eq (CantInferEq a)
cantInferEq :: (Eq (FooT a)) => Proxy a -> FooT a -> FooT a -> Bool
cantInferEq _ x y = x == y
Or you can avoid having to use UndecidableInstances
by packaging up the Eq (FooT a)
dictionary with the CantInferEq
constructor:
{-# LANGUAGE GADTs, StandaloneDeriving #-}
data CantInferEq a where
CantInferEq :: (Eq (FooT a)) => FooT a -> CantInferEq a
deriving instance Eq (CantInferEq a)
链接地址: http://www.djcxy.com/p/43146.html
上一篇: 说服GHC说`Maybe Void`是一种单位类型
下一篇: 使用关联类型族时推断类型类约束