简体   繁体   English

GADT与自定义数据类型的混淆?

[英]GADT confusion with custom data types?

I have the following custom data types: 我有以下自定义数据类型:

data FirstPair' a b = FirstPair a b deriving (Show, Ord, Eq)
type FirstPair a = FirstPair' a a 

data SecondPair' a b = SecondPair a b deriving (Show, Ord, Eq)
type SecondPair a = SecondPair' a a 

I'm trying to create a GADT structure for my function: 我正在尝试为我的函数创建一个GADT结构:

data Generator a where
  Success :: FirstPair a -> Generator (SecondPair a)
  Fail :: FirstPair a -> Generator Bool

myFunction :: Generator a -> a
myFunction (Success fp) = SecondPair "21" "24"
myFunction (Fail fp) = False

The role of 'Generator' type is to enable me to force 'myFunction' to return an instance of 'SecondPair' if 'Success' is passed to it, and 'False' if 'Fail' is passed to it. 'Generator'类型的作用是让我强制'myFunction'返回'SecondPair'的实例,如果'Success'被传递给它,并且'False'如果'Fail'传递给它。

However, I'm getting this error: 但是,我收到此错误:

"Could not deduce: a1 ~ [Char] from the context: a ~ SecondPair' a1 a1 bound by a pattern with constructor: Success :: forall a. FirstPair a -> Generator (SecondPair a)"

What am I doing wrong here? 我在这做错了什么?

myFunction :: Generator a -> a
myFunction (Success fp) = SecondPair "21" "24"
myFunction (Fail fp) = False

The problem is here. 问题出在这里。 The type signature is shorthand for 类型签名是简写

myFunction :: forall a. Generator a -> a

That is, no matter what type a I pick, if I give myFunction a Generator a , it will give me back an a . 也就是说,不管是什么类型a我去接,如果我给myFunction一个Generator a ,它会给我回来的a So if I gave it a Generator Int , it should give me back an Int . 所以,如果我给它一个Generator Int ,它应该给我一个Int

So I can construct 所以我可以构建

successval :: Generator (SecondPair Int)
successval = Success (FirstPair 42 42 :: FirstPair Int)

And then pass it to myFunction , and according to the type signature I should get 然后将它传递给myFunction ,并根据我应该得到的类型签名

myFunction successVal :: SecondPair Int

However, the way myFunction is defined, it will always give back a SecondPair String no matter what type I pass it, and that's the problem it's complaining about. 但是,定义myFunction的方式,无论我传递的是什么类型,它总会返回一个SecondPair String ,这就是它所抱怨的问题。

You need to somehow use the argument you are given if you want this kind of polymorphism. 如果你想要这种多态性,你需要以某种方式使用你给出的参数。 Eg 例如

myFunction (Success (FirstPair x y)) = SecondPair x y

would do the trick, because the x and y going out are the same type as the x and y coming in (and FirstPair and SecondPair match the way the GADT says they should). 会做的伎俩,因为xy走出去都是同一类型的xy在未来(和FirstPairSecondPair的方式匹配GADT说,他们应该)。

If you need to return a SecondPair String no matter what, then either myFunction 's type signature is wrong, needing to be something like 如果你需要返回一个SecondPair String ,那么myFunction的类型签名是错误的,需要像

 myFunction :: Generator a -> SecondPair String

(which doesn't act correctly in the case of Fail -- I have more to say if this is the route you actually want to go, but it's a bit more involved than I want to write for a shot-in-the-dark guess) (在Fail的情况下,这种行为不正确 - 我还有更多的话要说这是你真正想去的路线,但是它比我想写的黑暗中更多的参与猜测)

or the GADT needs to say that the result will be a SecondPair String . 或者GADT需要说结果将是SecondPair String

 data Generator a where
     Success :: FirstPair a -> Generator (SecondPair String)
     ...

I don't think these are terribly likely scenarios, I just thought they might help your understanding of the problem. 我不认为这些是非常可能的场景,我只是认为它们可能有助于您理解问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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