diff --git a/src/Data/Functor/Variant.purs b/src/Data/Functor/Variant.purs index 25ea428..b78092b 100644 --- a/src/Data/Functor/Variant.purs +++ b/src/Data/Functor/Variant.purs @@ -1,6 +1,7 @@ module Data.Functor.Variant ( VariantF , inj + , class VariantInjTagged, injTagged , prj , on , onMatch @@ -35,6 +36,7 @@ import Data.Variant.Internal (class Contractable, class VariantFMatchCases, clas import Partial.Unsafe (unsafeCrashWith) import Prim.Row as R import Prim.RowList as RL +import Record (get) import Type.Equality (class TypeEquals) import Type.Proxy (Proxy(..)) import Unsafe.Coerce (unsafeCoerce) @@ -135,6 +137,24 @@ inj p value = coerceV $ VariantFRep { type: reflectSymbol p, value, map } coerceV ∷ VariantFRep f a → VariantF r2 a coerceV = unsafeCoerce +class VariantInjTagged a f b | a → f, a → b where + -- | Injects value from a single field of record into variant + -- | + -- | ```purescript + -- | maybeAtFoo :: forall r. Variant (foo :: FProxy Maybe | r) Int + -- | maybeAtFoo = injTagged { foo: Just 42 } + -- | ``` + injTagged ∷ Record a → VariantF f b + +instance variantInjTagged ∷ + ( RL.RowToList r1 (RL.Cons sym (f a) RL.Nil) + , R.Cons sym (f a) () r1 + , R.Cons sym (FProxy f) rx r2 + , Functor f + , IsSymbol sym + ) ⇒ VariantInjTagged r1 r2 a where + injTagged = inj (SProxy ∷ SProxy sym) <<< get (SProxy ∷ SProxy sym) + -- | Attempt to read a variant at a given label. -- | ```purescript -- | case prj (SProxy :: SProxy "foo") maybeAtFoo of diff --git a/src/Data/Variant.purs b/src/Data/Variant.purs index 2f323fd..9a00ee8 100644 --- a/src/Data/Variant.purs +++ b/src/Data/Variant.purs @@ -1,6 +1,7 @@ module Data.Variant ( Variant , inj + , class VariantInjTagged, injTagged , prj , on , onMatch @@ -34,6 +35,7 @@ import Data.Variant.Internal (class Contractable, class VariantMatchCases, class import Partial.Unsafe (unsafeCrashWith) import Prim.Row as R import Prim.RowList as RL +import Record (get) import Unsafe.Coerce (unsafeCoerce) foreign import data Variant ∷ # Type → Type @@ -55,6 +57,23 @@ inj p value = coerceV $ VariantRep { type: reflectSymbol p, value } coerceV ∷ VariantRep a → Variant r2 coerceV = unsafeCoerce +class VariantInjTagged a b | a → b where + -- | Injects value from a single field of record into variant + -- | + -- | ```purescript + -- | intAtFoo :: forall r. Variant (foo :: Int | r) + -- | intAtFoo = injTagged { foo: 42 } + -- | ``` + injTagged ∷ Record a → Variant b + +instance variantInjTagged ∷ + ( RL.RowToList r1 (RL.Cons sym a RL.Nil) + , R.Cons sym a () r1 + , R.Cons sym a rx r2 + , IsSymbol sym + ) ⇒ VariantInjTagged r1 r2 where + injTagged = inj (SProxy ∷ SProxy sym) <<< get (SProxy ∷ SProxy sym) + -- | Attempt to read a variant at a given label. -- | ```purescript -- | case prj (SProxy :: SProxy "foo") intAtFoo of diff --git a/test/Variant.purs b/test/Variant.purs index 5dfeb8d..b183596 100644 --- a/test/Variant.purs +++ b/test/Variant.purs @@ -5,7 +5,7 @@ import Prelude import Data.List as L import Data.Maybe (Maybe(..), isJust) import Data.Symbol (reflectSymbol) -import Data.Variant (Variant, on, onMatch, case_, default, inj, prj, SProxy(..), match, contract, Unvariant(..), unvariant, revariant) +import Data.Variant (Variant, on, onMatch, case_, default, inj, prj, SProxy(..), match, contract, Unvariant(..), unvariant, revariant, injTagged) import Record.Builder (build, modify, Builder()) import Test.Assert (assert') import Effect (Effect) @@ -26,7 +26,7 @@ _baz ∷ SProxy "baz" _baz = SProxy foo ∷ ∀ r. Variant (foo ∷ Int | r) -foo = inj _foo 42 +foo = injTagged { foo: 42 } bar ∷ ∀ r. Variant (bar ∷ String | r) bar = inj _bar "bar" diff --git a/test/VariantF.purs b/test/VariantF.purs index f421c7a..69f7937 100644 --- a/test/VariantF.purs +++ b/test/VariantF.purs @@ -3,7 +3,7 @@ module Test.VariantF where import Prelude import Data.Either (Either(..)) -import Data.Functor.Variant (FProxy, SProxy(..), VariantF, case_, contract, default, inj, match, on, onMatch, prj, revariantF, unvariantF) +import Data.Functor.Variant (FProxy, SProxy(..), VariantF, case_, contract, default, inj, match, on, onMatch, prj, revariantF, unvariantF, injTagged) import Data.List as L import Data.Maybe (Maybe(..), isJust) import Data.Tuple (Tuple(..)) @@ -26,7 +26,7 @@ _baz ∷ SProxy "baz" _baz = SProxy foo ∷ ∀ r. VariantF (foo ∷ FProxy Maybe | r) Int -foo = inj _foo (Just 42) +foo = injTagged { foo: Just 42 } bar ∷ ∀ r. VariantF (bar ∷ FProxy (Tuple String) | r) Int bar = inj _bar (Tuple "bar" 42)