1
votes

Suppose we have a record type that is homogeneous.

type RecI = { a :: Int, b :: Int, c :: Int, d :: Int, e :: Int }

We want to get from it type with the same keys but different value type:

type RecS = { a :: String, b :: String, c :: String, d :: String, e :: String }

Is it possible to get RecS type without explicitly defining all the keys from RecI?

And the second part of the question, what is the best way to implement mapping function from one type to another:

mapItoS :: (Int -> String) -> RecI -> RecS

?

2

2 Answers

2
votes

To get a free-ish conversion from Int to String at type level, just give your record a parameter, then instantiate it with Int to get RecI and with String to get RecS:

type Rec a = { a :: a, b :: a, c :: a, d :: a, e :: a }
type RecI = Rec Int
type RecS = Rec String

To implement mapItoS, you can first convert to a Foreign.Object using fromHomogeneous, then map the function over it, then convert back to the record.

Unfortunately there is no toHomogeneous function, because in general you can't be sure that the Foreign.Object actually contains all required keys. But no matter: in this particular case you can be sure that it does, so you can get away with unsafeCoerce:

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

A small self plug which is strictly relevant to the question :-P I've just published a library which provides many instances which allow a PureScripter to work with homogeneous Record and Variant:

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

I think it should have much better inference than solutions like heterogeneous. Please check it out and let me know what do you think.