gho*_*orn 3 haskell types typeclass type-families
我知道您可以在关联的类型系列和数据系列上添加约束.这样做是对所有类的实例强制执行约束.
但我无法弄清楚如何在实例派生或函数声明中推断出这些约束.例如,此代码无法键入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
Run Code Online (Sandbox Code Playgroud)
错误消息是:
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.
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?是否有解决方法来实现我想要的行为?
问题的关键在于,只有a FooT a,你无处可拉Eq实例字典.
解决方法是在类型类要求中明确,从而有一个Eq传递dict 的地方:
{-# 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
Run Code Online (Sandbox Code Playgroud)
或者您可以通过使用构造函数UndecidableInstances打包Eq (FooT a)字典来避免使用CantInferEq:
{-# LANGUAGE GADTs, StandaloneDeriving #-}
data CantInferEq a where
CantInferEq :: (Eq (FooT a)) => FooT a -> CantInferEq a
deriving instance Eq (CantInferEq a)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
98 次 |
| 最近记录: |