假设我有
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)
答案 0 :(得分:1)
到目前为止,我能提出的最佳效果仍然使用fromJust
,但它更简单:
toFoo :: forall p.
(forall a. Maybe (p a))
-> Foo p
toFoo Nothing = NoFoo
toFoo m = YesFoo $ fromJust m