Skip to content

Create a partially applied record constructor #49

Open
@chrisdone

Description

@chrisdone

Consider this:

F <$> x <*> y <*> z

This has a problem traditionally that you need to make sure you get the x/y/z order correct. If you're making forms (web forms) with e.g. a formlet library, this becomes pretty hard to manage.

What if we could do this?

partially F <$> pure {x:a} <*> pure {y:b} <*> pure {z:a}

(or alternatively by using SProxy :: SProxy "a", etc.)

So that partially F would produce a function of one argument of one of the x, y or z fields (or more, I guess). When provided with one, it accepts another argument until all fields have been consumed.

I made special version of <*> that achieves something similar:

module Record.Apply where

import Control.Applicative
import Prim.Row (class Nub, class Union)
import Record (disjointUnion)

-- API

applyFields
  :: forall f inner outer combined.
     Union inner outer combined
  => Nub combined combined
  => Apply f
  => f { | inner }
  -> f { | outer }
  -> f { | combined }
applyFields getInner getOuter =
  disjointUnion <$> getInner <*> getOuter

infixl 5 applyFields as <|*>

-- Demo

newtype Foo = Foo { x :: Int, y :: String, z :: Array Int }

demo :: forall f. Applicative f => f Foo
demo = Foo <$> pure {y: ""} <|*> pure {x: 2} <|*> pure {z: []}

Which works nicely, but I think re-using <*> would be cool too. Any ideas?

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: documentationImprovements or additions to documentation.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions