Restricting input to a subset of a Variant

As an example, I can do something like the following:

data Foo = Foo (Variant (bar :: Int, baz :: Boolean))


type Bar v = (bar :: Int | v)

_bar = SProxy :: SProxy "bar"

bar :: forall v. Int -> Variant (Bar v)
bar = inj _bar


type Baz v = (baz :: Boolean | v)

_baz = SProxy :: SProxy "baz"

baz :: forall v. Boolean -> Variant (Baz v)
baz = inj _baz
someBar :: forall v. Variant (bar :: Int, baz :: Boolean | v) -> Maybe Foo
someBar =
  default Nothing
    # on _bar (Just <<< Foo <<< bar)

someBaz :: forall v. Variant (bar :: Int, baz :: Boolean | v) -> Maybe Foo
someBaz =
  default Nothing
    # on _baz (Just <<< Foo <<< baz)
> someBar $ bar 1 -- Just Foo
> someBar $ baz true -- Nothing
> someBaz $ bar 1 -- Nothing
> someBaz $ baz true -- Just Foo

However, I’d prefer to have each function only type check if it’s passed a row with the field it’s concerned about, like this:

someBar :: _ -> Foo
someBar = Foo

someBaz :: _ -> Foo
someBaz = Foo
> someBar $ bar 1 -- Foo
> someBar $ baz true -- Type error
> someBaz $ bar 1 -- Type error
> someBaz $ baz true -- Foo

It this possible?

Are you maybe looking for the expand function? https://pursuit.purescript.org/packages/purescript-variant/4.0.0/docs/Data.Variant#v:expand

someBar :: Variant (bar :: Int) -> Foo
someBar bar = Foo (expand bar)

someBaz :: Variant (baz :: Boolean) -> Foo
someBaz baz = Foo (expand baz)

Yes! Of course! Thanks @kritzcreek :slight_smile:

1 Like