Vinyl:rtraverse 具有需要所有字段共享约束的函数
Vinyl: rtraverse with a function requiring a constraint shared by all fields
我构建了一个 Vinyl 记录的简单示例。首先,一些语言编译指示和导入:
{-# LANGUAGE DataKinds, TypeOperators #-}
import Data.Vinyl
import Data.Vinyl.Functor
import Control.Applicative
实际示例(为简单起见,它使用 HList 类型同义词):
mytuple :: HList [Integer,Bool]
mytuple = Identity 4 :& Identity True :& RNil
编译成功。但现在我想使用 rtraverse:
打印黑胶唱片
printi :: Show a => Identity a -> IO (Identity a)
printi (Identity x) = print x *> pure (Identity x)
main :: IO ()
main = rtraverse printi mytuple *> pure ()
这会产生以下错误:No instance for (Show x) arising from a use of ‘printi’
。我猜这是预期的,因为 rtraverse
需要一个没有约束的函数。
如何解决这个问题?似乎 reifyConstraint
将成为解决方案的一部分,但我不知道如何使用它。
你是正确的,reifyConstraint 将解决这个问题。该函数的作用是将(或 "reify")约束转换为数据类型,即 Dict
数据类型。例如
>:t reifyConstraint (Proxy :: Proxy Show) mytuple
(reifyConstraint (Proxy :: Proxy Show) mytuple)
:: Rec (Dict Show :. Identity) '[Integer, Bool]
此记录中的每个元素都具有 Dict (Identity _)
的形式。 Dict
定义为
data Dict c x where Dict :: c x => x -> Dict c x
现在您只需要一个可以处理 (Dict Show :. Identity) a
作为输入的遍历函数。
printi :: Compose (Dict Show) Identity a -> IO (Compose (Dict Show) Identity a)
printi x@(Compose (Dict a)) = print a >> return x
请注意,您不需要 a
上的 Show
约束 - Show
class 字典存储在 Dict
数据类型中。您可以使用此功能进行遍历。
main = rtraverse printi (reifyConstraint (Proxy :: Proxy Show) mytuple)
我构建了一个 Vinyl 记录的简单示例。首先,一些语言编译指示和导入:
{-# LANGUAGE DataKinds, TypeOperators #-}
import Data.Vinyl
import Data.Vinyl.Functor
import Control.Applicative
实际示例(为简单起见,它使用 HList 类型同义词):
mytuple :: HList [Integer,Bool]
mytuple = Identity 4 :& Identity True :& RNil
编译成功。但现在我想使用 rtraverse:
打印黑胶唱片printi :: Show a => Identity a -> IO (Identity a)
printi (Identity x) = print x *> pure (Identity x)
main :: IO ()
main = rtraverse printi mytuple *> pure ()
这会产生以下错误:No instance for (Show x) arising from a use of ‘printi’
。我猜这是预期的,因为 rtraverse
需要一个没有约束的函数。
如何解决这个问题?似乎 reifyConstraint
将成为解决方案的一部分,但我不知道如何使用它。
你是正确的,reifyConstraint 将解决这个问题。该函数的作用是将(或 "reify")约束转换为数据类型,即 Dict
数据类型。例如
>:t reifyConstraint (Proxy :: Proxy Show) mytuple
(reifyConstraint (Proxy :: Proxy Show) mytuple)
:: Rec (Dict Show :. Identity) '[Integer, Bool]
此记录中的每个元素都具有 Dict (Identity _)
的形式。 Dict
定义为
data Dict c x where Dict :: c x => x -> Dict c x
现在您只需要一个可以处理 (Dict Show :. Identity) a
作为输入的遍历函数。
printi :: Compose (Dict Show) Identity a -> IO (Compose (Dict Show) Identity a)
printi x@(Compose (Dict a)) = print a >> return x
请注意,您不需要 a
上的 Show
约束 - Show
class 字典存储在 Dict
数据类型中。您可以使用此功能进行遍历。
main = rtraverse printi (reifyConstraint (Proxy :: Proxy Show) mytuple)