2017-07-07 80 views
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) 
+0

为了记录在案,我是你不使用签名'toFoo :: FORALL p猜测。 (由于“GHC还不支持impindicative多态性”错误消息,可能(全部a。p a)) - > Foo p'(这会使实现变得微不足道)。 – rampion

+0

@rampion,啊,现在我明白你的问题了。我认为这是一个有效的问题,但可能略有不同。 – dfeuer

+1

@rampion是不是等同于'(forall a。也许(p a)) - >也许(forall a。p a)''的问题?不是你的评论中的类型 –

回答

1

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

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

另一个令人厌恶的选择是匹配'Just'构造函数,然后'unsafeCoerce'的内容进行概括。 – dfeuer

相关问题