映射同类记录类型

Mapping homogeneous record type

假设我们有一个同类的记录类型。

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

?

要在类型级别获得从 IntString 的自由转换,只需为您的记录提供一个参数,然后使用 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,您可以先转换为 Foreign.Object using fromHomogeneous,然后将函数映射到它上面,然后再转换回记录。

不幸的是没有toHomogeneous函数,因为通常你不能确定Foreign.Object是否真的包含所有需要的键。但没关系:在这种特殊情况下,您可以确定它确实如此,因此您可以摆脱 unsafeCoerce:

mapItoS :: forall a b. (a -> b) -> Rec a -> Rec b
mapItoS f = fromHomogeneous >>> map f >>> unsafeCoerce

一个与问题严格相关的小型自插件:-P 我刚刚发布了一个库,它提供了许多允许 PureScripter 使用同类 RecordVariant 的实例:

https://pursuit.purescript.org/packages/purescript-homogeneous

我认为它应该比 heterogeneous 这样的解决方案有更好的推理。请检查一下,让我知道您的想法。