Skip to content

Instantly share code, notes, and snippets.

@paldepind
Created August 12, 2018 19:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paldepind/6ec923b94c6aab6915536580d6f0c466 to your computer and use it in GitHub Desktop.
Save paldepind/6ec923b94c6aab6915536580d6f0c466 to your computer and use it in GitHub Desktop.
module Experiment
( mapHeterogenousRecord
, mapRecordBuilder
, class MapRecord
) where
import Prelude
import Prim.Row as Row
import Prim.RowList as RL
import Record as R
import Record.Builder (Builder)
import Record.Builder as Builder
import Data.Maybe (Maybe(..))
import Data.Symbol (class IsSymbol, SProxy(SProxy))
import Type.Data.RowList (RLProxy(RLProxy))
mapHeterogenousRecord :: forall row xs f row'
. RL.RowToList row xs
=> MapRecord xs row f () row'
=> (forall a. a -> f a)
-> Record row
-> Record row'
mapHeterogenousRecord f r = Builder.build builder {}
where
builder = mapRecordBuilder (RLProxy :: RLProxy xs) f r
class MapRecord (xs :: RL.RowList) (row :: # Type) f (from :: # Type) (to :: # Type)
| xs -> row f from to where
mapRecordBuilder :: RLProxy xs -> (forall a. a -> f a) -> Record row -> Builder { | from } { | to }
instance mapRecordCons ::
( IsSymbol name -- name is a symbol
, Row.Cons name a trash row -- `name` and `a` is the head of `row`
, MapRecord tail row f from from' -- recursive invocation
, Row.Lacks name from'
, Row.Cons name (f a) from' to
) => MapRecord (RL.Cons name a tail) row f from to where
mapRecordBuilder _ f r =
first <<< rest
where
nameP = SProxy :: SProxy name
val = f $ R.get nameP r
rest = mapRecordBuilder (RLProxy :: RLProxy tail) f r
first = Builder.insert nameP val
instance mapRecordNil :: MapRecord RL.Nil row f () () where
mapRecordBuilder _ _ _ = identity
object = { foo: 1, bar: "baz" }
mapped = mapHeterogenousRecord Just object
> mapHeterogenousRecord pure { foo: 1, bar: "baz" } :: { foo :: Maybe Int, bar :: Maybe String }
{ foo: (Just 1), bar: (Just "baz") }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment