【发布时间】:2012-07-14 16:03:03
【问题描述】:
我有一个嵌套类型,我想使用关联的类型同义词部分指定它。下面是一些非常简化的代码来演示这个问题:
{-# LANGUAGE TypeFamilies,
FlexibleInstances,
FlexibleContexts,
MultiParamTypeClasses #-}
f :: Int -> Int
f x = x+1
data X t i
newtype Z i = Z i deriving (Eq,Show)
newtype Y q = Y (T q)
class Qux m r where
g :: (T m) -> r
class (Integral (T a)) => Foo a where
type T a
-- ... functions
instance (Integral i) => Foo (X (Z i) i) where
type T (X (Z i) i) = i
instance (Foo q) => Num (Y q) -- where ...
instance (Foo q, Foo (X m' Int)) => Qux (X m' Int) (Y q) where
g x = fromIntegral $ f $ x
其中(即使使用 UndecidableInstances)会导致编译器错误:
Could not deduce (T (X m' Int) ~ Int)
我知道将这个约束添加到 Qux 的实例会使编译器高兴。但是,我知道在我的程序中 (T (X arg1 arg2)) = arg2,所以我想弄清楚如何不必须编写此约束。
我的问题是:我能否让 Haskell 意识到,当我将 'Int' 作为 X 的第二个参数时,这(完全相同)与同义词 T (X a' Int) 相同?我意识到我正在使用关于我的实例外观的“特殊”知识,但我认为应该有一种方法可以将这一点传达给编译器。
谢谢
【问题讨论】:
-
我很难遵循这个。您向我们展示了
Qux类声明吗? “以相同方式嵌套的其他 Foo 实例”是什么意思? “根据 X 制作多个实例,但对于泛型 Z 和固定嵌套类型 i”是什么意思?此外,您提出的许多约束看起来都不是很好。 “我必须添加约束 S (T (X a')) ~ Int”就是这样一个。即使您将其充实到约束 S (T (X a' i)) ~ Int,这看起来也不正确;也许您的意思是 S (T (X a' i)) ~ a' 之类的东西?总体而言,这个问题可以进行一些校对。 -
感谢丹尼尔的评论,我希望我的编辑能让这个问题更容易理解。为了明确回答您的一些问题,Qux 的定义几乎无关紧要,它只是我正在制作的一些类的实例。我所说的“以相同方式嵌套”的意思是 Foo 的所有实例都将具有相同的类型。 (我想这就是我的意思......)我希望添加替代方法将澄清我的限制。
-
没有任何简单的示例来说明您想要做什么?
-
我还应该提到我完全关心类型同义词的原因:在某些情况下我想要一个实例 (Foo a => Qux a),它不限制 'X ' 或 'i' (所以我无法直接访问 'i' 参数)。另一个例子是我有一个数据(H x),我希望 x 是 Foo 的一个实例。然后我将 H 定义为 (data H x = H (S (T x))),这样 H 就不必携带类型参数 S (T x)。
-
代码现在可以编译了。删除实例约束 (S (T (X m' Int)) ~ Int),这是我试图弄清楚如何做的,会产生编译器错误。
标签: haskell type-families