Haskell 如何将这两种数据类型:`RowF-Maybe`和`Maybe(RowF-Identity)`放在同一个列表中?
我有以下数据类型:Haskell 如何将这两种数据类型:`RowF-Maybe`和`Maybe(RowF-Identity)`放在同一个列表中?,haskell,types,Haskell,Types,我有以下数据类型: data RowF f = RowF { rsidf :: f String , rtimef :: f Double } type Row = RowF Identity realizeRow :: RowF Maybe -> Maybe Row 我想要一个行和行的列表。也就是说,我可能: [RowF (Maybe "hello") Nothing, Maybe
data RowF f = RowF { rsidf :: f String
, rtimef :: f Double
}
type Row = RowF Identity
realizeRow :: RowF Maybe -> Maybe Row
我想要一个行
和行
的列表。也就是说,我可能:
[RowF (Maybe "hello") Nothing, Maybe (RowF "world" 12.3)]
有人建议我应该实现一些功能:
f :: (forall x. f x -> g x) -> RowF f -> RowF g
但我不确定这意味着什么或如何实施 有两种解决方案 您可以使用
或包装这两种类型:
ghci> let rm = RowF (Just "hello") Nothing :: RowF Maybe
ghci> let mr = Just (RowF (Identity "world") (Identity 12.3)) :: Maybe Row
ghci> :t [ Left rm, Right mr ]
[ Left rm, Right mr ] :: [ Either (RowF Maybe) (Maybe Row) ]
或者,您可以创建一些函数来来回转换
toRow :: Applicative f => RowF f -> f Row
toRow (RowF fs fd) = (\s d -> RowF (Identity s) (Identity d)) <$> fs <*> fd
fromRow :: Functor f => f Row -> RowF f
fromRow fr = RowF (runIdentity . rsidf <$> fr) (runIdentity . rtimef <$> fr)
或者,您可以创建一个包装器来包装所有RowF
,并使用该包装器:
ghci> :set -XRankNTypes -XConstraintKinds -XExistentialQuantification
ghci> data RowC c = forall f. RowC { runRowC :: c f => RowF f }
ghci> let ri = RowF (Identity "world") (Identity 12.3) :: Row
ghci> :t [ RowC rm, RowC ri ] :: [ RowC Monad ]
[ RowC rm, RowC ri ] :: [ RowC Monad ] :: [RowC Monad]
这种方法的缺点是,一旦您将RowF
转换为RowC
,您就无法再转换回去,也无法执行任何操作
使用约束c
定义的操作之外的值
你得到的最后一个建议,定义
convert :: (forall x. f x -> g x) -> RowF f -> RowF g
convert f2g (RowF fs fd) = RowF (f2g fs) (f2g fd)
将允许您轻松地从行
转换为行
ghci> :t convert (Just . runIdentity) ri
convert (Just . runIdentity) ri :: RowF Maybe
你为什么要这个?那些中的一些可能是仅仅是s吗?为了澄清@dfeuer在说什么。。。为什么要有一个同时包含RowF Identify
和RowF Maybe
值的列表?向我们展示一些您想要编写的示例代码,如果您可以构建这样一个列表的话。
ghci> :t convert (Just . runIdentity) ri
convert (Just . runIdentity) ri :: RowF Maybe