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