[英]How can I prove to GHC that (b ~ Foo)?
我不会假装我知道如何思考或谈论哈斯克尔。 在伪java-oo-jargon中:
我想要做的是有一个“实现”“接口”的“结构”。 该接口的一部分是一个返回实现另一个接口的对象的函数。
interface IFiz {}
interface IBuz {
function IFiz getFiz()
}
class Foo implements IFiz { ... }
class Bar implements IBuz {
IFiz fiz = new Foo();
function getFiz() {
return fiz;
}
}
我怎么能在Haskell中做到这一点? 我这样做的尝试如下所述。
我怎样才能向GHC证明(b~Foo)?
我对这个问题的理解:
Foo是类型类Fiz的一个实例。
我希望Bar成为类型Buz的一个实例。
但是,编译器无法在punk
方法的实现中推断出(b~Foo)。 但还有什么呢? 我尝试使用不推荐的直接方式添加数据约束,以及使用GADT,但似乎都没有工作(我继续得到完全相同的错误。)
data Foo = Foo Int
data Bar = Bar Foo
class Fiz a where
funk :: a -> a -- Not important, I just wanted to put something in Fiz
class Buz a where
punk :: Fiz b => a -> b
instance Fiz Foo where
funk a = a
instance Buz Bar where
punk (Bar foo) = foo
Could not deduce (b ~ Foo)
from the context (Fiz b)
bound by the type signature for punk :: Fiz b => Bar -> b
at Test.hs:42:5-8
‘b’ is a rigid type variable bound by
the type signature for punk :: Fiz b => Bar -> b at Test.hs:42:5
Relevant bindings include punk :: Bar -> b (bound at Test.hs:42:5)
In the expression: foo
In an equation for ‘punk’: punk (Bar foo) = foo
此类型签名:
class Buz a where
punk :: Fiz b => a -> b
说punk
必须能够为任何类型b
返回类型b
东西,因为它是Fiz
实例。 所以问题不在于编译器不能推断出Foo
是Fiz
实例,而是返回值不是Quux
,这是Fiz
一个实例。
data Quux = Quux
instance Fiz Quux where
funk a = a
如果你想让函数类型返回任何Fiz
实例,你可以使用ExistentionalQuantification扩展:
{-# LANGUAGE RankNTypes, ExistentialQuantification #-}
data Foo = Foo Int
data Bar = Bar Foo
data SomeFiz = forall a . Fiz a => SomeFiz a
class Fiz a where
funk :: a -> a
class Buz a where
punk :: a -> SomeFiz
instance Fiz Foo where
funk a = a
instance Buz Bar where
punk (Bar foo) = SomeFiz foo
否则,如果你真的想要实现这个类型类,你只能通过将底部传递给funk
:
instance Buz Bar where
punk _ = funk undefined
-- or for example:
instance Buz Bar where
punk _ = funk (funk undefined)
或者通过修复funk:
instance Buz Bar where
punk _ = fix funk
如果你能提供你想要达到的目标的更多细节,也许我会给出更多有用的答案。
你不能。
Buz
类说如果a
有一个Buz
实例,那么对于每个有一个Fiz
实例的b
,你可以从a -> b
提供一个函数。 Fiz
在制作b
几乎没有任何帮助; funk
只会给你一个b
,如果你已经有了一个b
。
您可能误解了GHC的错误消息。 类型推断是双向的。 在这种情况下, b
来自Buz
类中的punk
签名。 它要求的结果punk
是类型的东西b
每种类型b
。 Foo
不是所有类型的东西。
‘b’ is a rigid type variable bound by
the type signature for punk :: Fiz b => Bar -> b at Test.hs:42:5
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.