Предположим, что
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)