10
data Foo p =
NoFoo
| YesFoo (forall a. p a)
我可以写
fromFoo :: Foo p -> Maybe (p a)
fromFoo NoFoo = Nothing
fromFoo (YesFoo p) = Just p
它也可以走另一条路:
toFoo :: forall p.
(forall a. Maybe (p a))
-> Foo p
toFoo m =
case m :: Maybe (p()) of
Nothing -> NoFoo
Just _ -> YesFoo (fromJust m)
的fromJust
是恶心! toFoo
实际上是总数,因为参数确保m @a
的行为与m @()
的行为完全相同,但这是严重的。有没有更清洁的方法?
编辑:rampion指出,这可以写得更简洁,仍然与fromJust
。我才意识到这是可以做到一点幽默,使得新手的乐趣:
toFoo m
| isNothing m = NoFoo
| otherwise = YesFoo (fromJust m)
我看,以避免产生一个thunk申请fromJust
的唯一途径是通过获取超级邪恶:
toFoo Nothing = NoFoo
toFoo (Just x) = YesFoo (unsafeCoerce# x)
为了记录在案,我是你不使用签名'toFoo :: FORALL p猜测。 (由于“GHC还不支持impindicative多态性”错误消息,可能(全部a。p a)) - > Foo p'(这会使实现变得微不足道)。 – rampion
@rampion,啊,现在我明白你的问题了。我认为这是一个有效的问题,但可能略有不同。 – dfeuer
@rampion是不是等同于'(forall a。也许(p a)) - >也许(forall a。p a)''的问题?不是你的评论中的类型 –