Last active
July 17, 2019 19:26
-
-
Save safareli/596c5993362f7477c380a8e66a80d158 to your computer and use it in GitHub Desktop.
SProxies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | This is module defines modified version `SProxies` and `mkSProxies` from [here][Row] ([depending on this][Utils]). | |
-- | That code was licensed with [Apache License 2.0][License] | |
-- | | |
-- | [Row] - https://github.com/thomashoneyman/purescript-halogen-formless/blob/55e2453f8e0d9169ec3cdccdd8cc09c0e289ffea/src/Formless/Transform/Row.purs#L61-L100 | |
-- | [Utils] - https://github.com/thomashoneyman/purescript-halogen-formless/blob/55e2453f8e0d9169ec3cdccdd8cc09c0e289ffea/src/Formless/Internal/Transform.purs#L23-L35 | |
-- | [License] - https://github.com/thomashoneyman/purescript-halogen-formless/blob/55e2453f8e0d9169ec3cdccdd8cc09c0e289ffea/LICENSE | |
module Type.SProxies | |
( SProxies | |
, SProxies' | |
, mkSProxies | |
, class MakeSProxies | |
, makeSProxiesBuilder | |
) | |
where | |
import Prelude | |
import Data.Identity (Identity) | |
import Data.Newtype (class Newtype) | |
import Data.Symbol (class IsSymbol, SProxy(..)) | |
import Prim.Row as Row | |
import Prim.RowList as RL | |
import Record.Builder (Builder) | |
import Record.Builder as Builder | |
import Type.Proxy (Proxy(..)) | |
import Type.Row (RLProxy(..)) | |
-- | A type to collect constraints necessary to apply to prove that a record of | |
-- | SProxies is compatible with your type, which was constructed by some type | |
-- | constructor of form `# Type -> Type` (Record, Variant ...) | |
type SProxies t = ∀ container xs inputs row . SProxies' (Identity t) container xs inputs row | |
-- | A helper function to produce a record of SProxies given a type, to save | |
-- | you the boilerplate of writing them all out. | |
-- | | |
-- | ```purs | |
-- | type T = {foo :: Int, baz :: Int} | |
-- | | |
-- | prx :: SProxies T | |
-- | prx = mkSProxies (Proxy :: Proxy T) | |
-- | | |
-- | x :: SProxy "foo" | |
-- | x = prx.foo | |
-- | ``` | |
mkSProxies | |
:: ∀ t container xs inputs row | |
. Proxy t | |
-> SProxies' (Identity t) container xs inputs row | |
mkSProxies _ = mkSProxies' (Proxy :: Proxy (Identity t)) | |
-- | It's just common part of `mkSProxies` `SProxies` so we DRY. | |
type SProxies' t container xs inputs row | |
= Newtype t (container inputs) | |
=> RL.RowToList inputs xs | |
=> MakeSProxies xs row | |
=> Record row | |
-- | For `SProxies` to work, you want `xs row inputs` to be unsolved type | |
-- | variables and only way so far is to use Newtype, as it stops solving. | |
-- | Because of this, we not only have `mkSProxies'` and `SProxies'`, but | |
-- | we also have `mkSProxies` and `SProxies` so users don't have to | |
-- | use some newtype around there types. i.e. without `mkSProxies` and `SProxies` | |
-- | user would have to do this: | |
-- | | |
-- | ```purs | |
-- | type T = {foo :: Int, baz :: Int} | |
-- | | |
-- | prx :: SProxies (Identity T) | |
-- | prx = mkSProxies (Proxy :: Proxy (Identity T)) | |
-- | | |
-- | x :: SProxy "foo" | |
-- | x = prx.foo | |
-- | ``` | |
mkSProxies' | |
:: ∀ t container xs inputs row | |
. Proxy t | |
-> SProxies' t container xs inputs row | |
mkSProxies' _ = fromScratch builder | |
where | |
builder = makeSProxiesBuilder (RLProxy :: RLProxy xs) | |
-- | The class used to build up a new record of symbol proxies from an | |
-- | input row list. | |
class MakeSProxies (xs :: RL.RowList) (to :: # Type) | xs -> to where | |
makeSProxiesBuilder :: RLProxy xs -> FromScratch to | |
instance makeSProxiesNil :: MakeSProxies RL.Nil () where | |
makeSProxiesBuilder _ = identity | |
instance makeSProxiesCons | |
:: ( IsSymbol name | |
, Row.Cons name (SProxy name) from to | |
, Row.Lacks name from | |
, MakeSProxies tail from | |
) | |
=> MakeSProxies (RL.Cons name x tail) to where | |
makeSProxiesBuilder _ = first <<< rest | |
where | |
rest = makeSProxiesBuilder (RLProxy :: RLProxy tail) | |
first = Builder.insert (SProxy :: SProxy name) (SProxy :: SProxy name) | |
-- | Apply a builder that produces an output record from an empty record | |
fromScratch :: ∀ r. FromScratch r -> Record r | |
fromScratch = Builder.build <@> {} | |
-- | Represents building some output record from an empty record | |
type FromScratch r = Builder {} (Record r) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment