默认值受 haskell 中的存在约束
Default values subject to existential constraint in haskell
考虑以下定义类型对的类型类:
class Constraint a b where
g :: a -> b
对于约束的所有实例,我们可以派生出一组类型 a
,本质上是一个隐式类型类,我们称它为 A
。对于类型类 A
的每个实例,还有另一个隐式类型类 B
,它包括 Constraint A b
.
的所有可能类型 b
所以这是一段代码。
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Debug.Trace
-- Contraining class
class (Show a, Show b) => QandA a b where
g :: a -> b
-- Some data types
data A = A1 | A2 deriving (Show, Eq)
data B = B1 | B2 deriving (Show, Eq)
data C = C1 | C2 deriving (Show, Eq)
instance QandA A B where
g A1 = B1
g A2 = B2
instance QandA A C where
g A1 = C1
g A2 = C2
-- We want to define a set of types that includes all the types that
-- have Constraint a b given a. This can be done via an intermediate
-- type.
data DefaultAnswer q = forall a . (DefaultingQuestion q, QandA q a) => DefaultAnswer {answer :: a};
-- Polymorphism
class DefaultingQuestion q where
def :: DefaultAnswer q
instance DefaultingQuestion A where
def = DefaultAnswer C1
在 ghci 中进行类型检查
> (def :: DefaultAnswer A)
(def :: DefaultAnswer A) :: DefaultAnswer A
但是
> answer (def :: DefaultAnswer A)
<interactive>:574:1:
Cannot use record selector "answer" as a function due to escaped type variables
Probable fix: use pattern-matching syntax instead
In the expression: answer (def :: DefaultAnswer A)
In an equation for "it": it = answer (def :: DefaultAnswer A)
现在我的理解是,因为我使用存在类型,GHC 并不真正寻找 answer
的类型,它只是确保可能有一个,即使它没有办法找出它是哪一个。所以当我真正想要 运行 answer
时,它无法弄清楚如何处理它。
所以我的问题是:有没有办法为实现 DefaultingQuestion
的每种类型定义默认答案
为什么不呢:
import Data.Proxy
class DefaultingQuestion q a where
def :: Proxy q -> a
instance DefaultingQuestion A where
def _ = C1
考虑以下定义类型对的类型类:
class Constraint a b where
g :: a -> b
对于约束的所有实例,我们可以派生出一组类型 a
,本质上是一个隐式类型类,我们称它为 A
。对于类型类 A
的每个实例,还有另一个隐式类型类 B
,它包括 Constraint A b
.
b
所以这是一段代码。
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Debug.Trace
-- Contraining class
class (Show a, Show b) => QandA a b where
g :: a -> b
-- Some data types
data A = A1 | A2 deriving (Show, Eq)
data B = B1 | B2 deriving (Show, Eq)
data C = C1 | C2 deriving (Show, Eq)
instance QandA A B where
g A1 = B1
g A2 = B2
instance QandA A C where
g A1 = C1
g A2 = C2
-- We want to define a set of types that includes all the types that
-- have Constraint a b given a. This can be done via an intermediate
-- type.
data DefaultAnswer q = forall a . (DefaultingQuestion q, QandA q a) => DefaultAnswer {answer :: a};
-- Polymorphism
class DefaultingQuestion q where
def :: DefaultAnswer q
instance DefaultingQuestion A where
def = DefaultAnswer C1
在 ghci 中进行类型检查
> (def :: DefaultAnswer A)
(def :: DefaultAnswer A) :: DefaultAnswer A
但是
> answer (def :: DefaultAnswer A)
<interactive>:574:1:
Cannot use record selector "answer" as a function due to escaped type variables
Probable fix: use pattern-matching syntax instead
In the expression: answer (def :: DefaultAnswer A)
In an equation for "it": it = answer (def :: DefaultAnswer A)
现在我的理解是,因为我使用存在类型,GHC 并不真正寻找 answer
的类型,它只是确保可能有一个,即使它没有办法找出它是哪一个。所以当我真正想要 运行 answer
时,它无法弄清楚如何处理它。
所以我的问题是:有没有办法为实现 DefaultingQuestion
为什么不呢:
import Data.Proxy
class DefaultingQuestion q a where
def :: Proxy q -> a
instance DefaultingQuestion A where
def _ = C1