1

下面的代码片段从Haskell wiki 借用了一个类型类字典和一个存在类型:

{-# language ExistentialQuantification #-}
module Experiment1 where

data Showable = forall x. Show x => Showable x
instance Show Showable where showsPrec p (Showable x) = showsPrec p x

resultStr :: String
resultStr = show (Showable ()) -- "()"

是否可以编写一个f :: (forall x. x -> result) -> result能够将Showable构造函数(或任何其他存在类型的数据构造函数)作为参数的函数?

一次失败的尝试如下所示:

{-# language ExistentialQuantification, RankNTypes, ConstraintKinds #-}

module Experiment2 where

-- import Data.Constraint (Dict(..), withDict)

data Showable = forall x. Show x => Showable x
instance Show Showable where showsPrec p (Showable x) = showsPrec p x

f :: (cxt (), cxt result) => (forall x. cxt x => x -> result) -> result
f mkResult = mkResult ()

resultStr :: String
resultStr = show (f Showable)

正如我上面评论的导入所暗示的那样,我的印象是约束包可能允许我传递必要的证明,但我看不出它是如何工作的?

4

2 回答 2

1

如果您提供一种方法来确定您的失败尝试是否有效cxt

import Data.Proxy

f :: (cxt (), cxt result) => p cxt -> (forall x. cxt x => x -> result) -> result
f _ mkResult = mkResult ()

resultStr :: String
resultStr = show (f (Proxy :: Proxy Show) Showable)
于 2018-01-03T03:43:41.333 回答
0

我很抱歉发布我自己的答案,但这是我最终找到的另一种选择:

{-# language ExistentialQuantification, RankNTypes, ConstraintKinds, KindSignatures, TypeFamilies, FlexibleInstances #-}

module Experiment3 where

import GHC.Exts

data Showable (cxt :: * -> Constraint) = forall x. (cxt ~ Show, cxt x) => Showable x
instance Show (Showable Show) where showsPrec p (Showable x) = showsPrec p x

f :: cxt () => (forall x. cxt x => x -> result cxt) -> result cxt
f mkResult = mkResult ()

resultStr :: String
resultStr = show (f Showable :: Showable Show)

不幸的是,它需要一个明确的类型签名,show (f Showable)而我的目标是通过Showable. 所以这个答案不是这样的解决方案,而是我想要的另一个反例。

我会接受 Cirdec 的回答,因为它引导我得出这个结论。

于 2018-01-03T05:42:38.853 回答