如何使用 Rank-2 类型抽象函数中的约束?
How to abstract constraints in function with Rank-2 type?
以下代码片段借鉴了 the 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)
正如我上面评论的导入所暗示的,我的印象是 constraints 包可能允许我传递必要的证明,但我看不出它是如何工作的?
如果您提供一种方法来确定 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)
对于发布我自己的答案,我深表歉意,但这是我最终找到的另一种选择:
{-# 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 的回答,因为它引导我得出这个结论。
以下代码片段借鉴了 the 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)
正如我上面评论的导入所暗示的,我的印象是 constraints 包可能允许我传递必要的证明,但我看不出它是如何工作的?
如果您提供一种方法来确定 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)
对于发布我自己的答案,我深表歉意,但这是我最终找到的另一种选择:
{-# 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 的回答,因为它引导我得出这个结论。