简体   繁体   English

我怎样才能向GHC证明(b~Foo)?

[英]How can I prove to GHC that (b ~ Foo)?

New Question 新问题

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. 我这样做的尝试如下所述。


Old Question 老问题

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 . 所以问题不在于编译器不能推断出FooFiz实例,而是返回值不是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM