有没有办法在声音时推动foralls过去的构造函数?

dfe*_*uer 10 haskell

假设我有

data Foo p =
    NoFoo
  | YesFoo (forall a. p a)
Run Code Online (Sandbox Code Playgroud)

我可以写

fromFoo :: Foo p -> Maybe (p a)
fromFoo NoFoo = Nothing
fromFoo (YesFoo p) = Just p
Run Code Online (Sandbox Code Playgroud)

它也可以走另一条路:

toFoo :: forall p.
         (forall a. Maybe (p a))
      -> Foo p
toFoo m =
  case m :: Maybe (p ()) of
    Nothing -> NoFoo
    Just _ -> YesFoo (fromJust m)
Run Code Online (Sandbox Code Playgroud)

fromJust是恶心!toFoo实际上是总数,因为参数确保m @a行为完全相同m @(),但这是粗略的.有没有更干净的方式?

编辑:rampion指出,这可以写得更简洁,仍然有fromJust.我刚刚意识到它可以做得有点幽默,取笑新手:

toFoo m
  | isNothing m = NoFoo
  | otherwise = YesFoo (fromJust m)
Run Code Online (Sandbox Code Playgroud)

我认为避免创建一个thunk以应用的唯一方法fromJust是获得超级邪恶:

toFoo Nothing = NoFoo
toFoo (Just x) = YesFoo (unsafeCoerce# x)
Run Code Online (Sandbox Code Playgroud)

ram*_*ion 1

到目前为止我能想到的最好的方法仍然是使用fromJust,但它更简单:

toFoo :: forall p.
         (forall a. Maybe (p a))
      -> Foo p
toFoo Nothing = NoFoo
toFoo m = YesFoo $ fromJust m
Run Code Online (Sandbox Code Playgroud)