[英]How can I prove to GHC that (b ~ Foo)?
I'm not going to pretend that I know how to think or talk about haskell. 我不会假装我知道如何思考或谈论哈斯克尔。 In pseudo-java-oo-jargon:
在伪java-oo-jargon中:
What I want to do is have a "structure" that "implements" an "interface." 我想要做的是有一个“实现”“接口”的“结构”。 Part of that interface is a function which returns an object which implements another interface.
该接口的一部分是一个返回实现另一个接口的对象的函数。
interface IFiz {}
interface IBuz {
function IFiz getFiz()
}
class Foo implements IFiz { ... }
class Bar implements IBuz {
IFiz fiz = new Foo();
function getFiz() {
return fiz;
}
}
How can I do this in Haskell? 我怎么能在Haskell中做到这一点? My attempt at doing this is described below.
我这样做的尝试如下所述。
How can I prove to GHC that (b ~ Foo)? 我怎样才能向GHC证明(b~Foo)?
My understanding of the problem: 我对这个问题的理解:
Foo is an instance of the type class Fiz. Foo是类型类Fiz的一个实例。
I would like Bar to be an instance of the type class Buz. 我希望Bar成为类型Buz的一个实例。
However, the compiler is unable to deduce that (b ~ Foo) in the implementation of the punk
method. 但是,编译器无法在
punk
方法的实现中推断出(b~Foo)。 But what else could it be? 但还有什么呢? I attempted to add data constraints using the deprecated direct way, as well as using GADTs, but neither seemed to work (I continued to get the exact same error.)
我尝试使用不推荐的直接方式添加数据约束,以及使用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
This type signature: 此类型签名:
class Buz a where
punk :: Fiz b => a -> b
says that punk
must be able to return something of type b
for any type b
given it is instance of Fiz
. 说
punk
必须能够为任何类型b
返回类型b
东西,因为它是Fiz
实例。 So the problem is not that compiler cannot deduce that Foo
is instance of Fiz
, but that the return value is not Quux
, which is an instance of Fiz
. 所以问题不在于编译器不能推断出
Foo
是Fiz
实例,而是返回值不是Quux
,这是Fiz
一个实例。
data Quux = Quux
instance Fiz Quux where
funk a = a
If you want to have type class with function returning any instance of Fiz
, you can use ExistentionalQuantification extension: 如果你想让函数类型返回任何
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
Otherwise if you really mean to implement this typeclass, you can only do this by passing bottoms to funk
: 否则,如果你真的想要实现这个类型类,你只能通过将底部传递给
funk
:
instance Buz Bar where
punk _ = funk undefined
-- or for example:
instance Buz Bar where
punk _ = funk (funk undefined)
or by fixing funk: 或者通过修复funk:
instance Buz Bar where
punk _ = fix funk
If you could give more details on what you want to achieve, maybe I'll be able to give more helpful answer. 如果你能提供你想要达到的目标的更多细节,也许我会给出更多有用的答案。
You can't. 你不能。
The class Buz
says that if a
has an instance for Buz
, then for every b
that has a Fiz
instance, you can provide a function from a -> b
. Buz
类说如果a
有一个Buz
实例,那么对于每个有一个Fiz
实例的b
,你可以从a -> b
提供一个函数。 The class Fiz
provides virtually no help in producing a b
; Fiz
在制作b
几乎没有任何帮助; funk
will only give you a b
if you already have a b
. funk
只会给你一个b
,如果你已经有了一个b
。
You are probably misunderstanding the error message from GHC. 您可能误解了GHC的错误消息。 Type inference goes both ways.
类型推断是双向的。 In this case,
b
comes from the signature for punk
in the class Buz
. 在这种情况下,
b
来自Buz
类中的punk
签名。 It requires that the result of punk
be something of type b
for every type b
. 它要求的结果
punk
是类型的东西b
每种类型b
。 Foo
is not something of every type. 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.