假设我们有一个同构的记录类型。
type RecI = { a :: Int, b :: Int, c :: Int, d :: Int, e :: Int }
我们想从中获得具有相同密钥但不同值类型的类型:
type RecS = { a :: String, b :: String, c :: String, d :: String, e :: String }
是否可以在不显式定义RecI
的所有密钥的情况下获得RecS
类型?
问题的第二部分,实现从一种类型到另一种类型的映射功能的最佳方法是什么:
mapItoS :: (Int -> String) -> RecI -> RecS
要在类型级别获得从Int
到String
的免费ish转换,只需给您的记录一个参数,然后用Int
实例化它以获得RecI
,用String
实例化它以获取RecS
:
type Rec a = { a :: a, b :: a, c :: a, d :: a, e :: a }
type RecI = Rec Int
type RecS = Rec String
要实现mapItoS
,您可以首先使用fromHomogeneous
转换为Foreign.Object
,然后在其上映射函数,然后转换回记录。
不幸的是,没有toHomogeneous
函数,因为通常情况下,您无法确定Foreign.Object
是否包含所有必需的密钥。但没关系:在这种特殊情况下,你可以确信它确实存在,所以你可以逃脱unsafeCoerce
:
mapItoS :: forall a b. (a -> b) -> Rec a -> Rec b
mapItoS f = fromHomogeneous >>> map f >>> unsafeCoerce
一个与以下问题严格相关的小型自插件:-p我刚刚发布了一个库,它提供了许多实例,允许PureScripter使用同构的Record
和Variant
:
https://pursuit.purescript.org/packages/purescript-homogeneous
我认为它应该比heterogeneous
这样的解决方案有更好的推断。请检查一下,让我知道你的想法。