有幾個解決方案。
你可以使用Either
來包裝兩種類型:
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)
然後就轉化爲一種其他的需要。
ghci> :t [ rm, fromRow mr ]
[ rm, fromRow mr ] :: [RowF Maybe]
ghci> :t [ toRow rm, mr ]
[ toRow rm, mr ] :: [Maybe Row]
或者,您可以創建一個包裝所有RowF f
的包裝,並使用:
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 f
到RowC c
,你不能轉換返回,並且您無法執行任何操作 以及約束c
定義的操作之外的任何值。
,你有最後的建議,確定
convert :: (forall x. f x -> g x) -> RowF f -> RowF g
convert f2g (RowF fs fd) = RowF (f2g fs) (f2g fd)
將允許你轉換從到RowF Maybe
容易。
ghci> :t convert (Just . runIdentity) ri
convert (Just . runIdentity) ri :: RowF Maybe
爲什麼要這樣?這些「可能」中的一些應該是「只是」嗎? – dfeuer
爲了澄清@dfeuer在說什麼......爲什麼你想要一個包含'RowF Identify'和'RowF Maybe'值的列表?向我們展示一些您想要編寫的示例代碼,如果您可以構建這樣的列表。 – ErikR