Подтвердить что ты не робот

Есть ли способ толкнуть форварды прошлых конструкторов, когда звук?

Предположим, что

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)
4b9b3361

Ответ 1

Лучшее, что я могу придумать, до сих пор использует fromJust, но это проще:

toFoo :: forall p.
         (forall a. Maybe (p a))
      -> Foo p
toFoo Nothing = NoFoo
toFoo m = YesFoo $ fromJust m