lorentz-0.4.0: EDSL for the Michelson Language
Safe HaskellNone
LanguageHaskell2010

Lorentz.UStore

Description

This module contains implementation of UStore.

UStore is essentially Store modified for the sake of upgradeability.

In API it differs from Store in the following ways: 1. It keeps both virtual big_maps and plain fields; 2. Neat conversion between Michelson and Haskell values is implemented; 3. Regarding composabililty, one can operate with one UStore and then lift it to a bigger one which includes the former. This allows for simpler management of stores and clearer error messages. In spite of this, operations with UStores over deeply nested templates will still work as before.

We represent UStore as big_map bytes bytes.

  • Plain fields are stored as key = pack fieldName; value = pack originalValue.
  • Virtual big_maps are kept as key = pack (bigMapName, originalKey); value = pack originalValue.
Synopsis

UStore and related type definitions

data UStore (a :: Type) Source #

Gathers multple fields and BigMaps under one object.

Type argument of this datatype stands for a "store template" - a datatype with one constructor and multiple fields, each containing an object of type UStoreField or |~> and corresponding to single virtual field or BigMap respectively. It's also possible to parameterize it with a larger type which is a product of types satisfying the above property.

Instances

Instances details
Eq (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

(==) :: UStore a -> UStore a -> Bool #

(/=) :: UStore a -> UStore a -> Bool #

Show (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

showsPrec :: Int -> UStore a -> ShowS #

show :: UStore a -> String #

showList :: [UStore a] -> ShowS #

Generic (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Associated Types

type Rep (UStore a) :: Type -> Type #

Methods

from :: UStore a -> Rep (UStore a) x #

to :: Rep (UStore a) x -> UStore a #

Semigroup (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

(<>) :: UStore a -> UStore a -> UStore a #

sconcat :: NonEmpty (UStore a) -> UStore a #

stimes :: Integral b => b -> UStore a -> UStore a #

Monoid (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

mempty :: UStore a #

mappend :: UStore a -> UStore a -> UStore a #

mconcat :: [UStore a] -> UStore a #

Default (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

def :: UStore a #

Wrapped (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Associated Types

type Unwrapped (UStore a) #

Methods

_Wrapped' :: Iso' (UStore a) (Unwrapped (UStore a)) #

UStoreTemplateHasDoc template => TypeHasDoc (UStore template) Source # 
Instance details

Defined in Lorentz.UStore.Doc

Associated Types

type TypeDocFieldDescriptions (UStore template) :: FieldDescriptions #

IsoValue (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Associated Types

type ToT (UStore a) :: T #

Methods

toVal :: UStore a -> Value (ToT (UStore a)) #

fromVal :: Value (ToT (UStore a)) -> UStore a #

GetOpHs (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Associated Types

type GetOpKeyHs (UStore a) Source #

type GetOpValHs (UStore a) Source #

UpdOpHs (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Associated Types

type UpdOpKeyHs (UStore a) Source #

type UpdOpParamsHs (UStore a) Source #

MemOpHs (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Associated Types

type MemOpKeyHs (UStore a) Source #

HasTypeAnn (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

getTypeAnn :: Notes (ToT (UStore a)) Source #

HasUField fname ftype templ => StoreHasField (UStore templ) fname ftype Source # 
Instance details

Defined in Lorentz.UStore.Instances

Methods

storeFieldOps :: StoreFieldOps (UStore templ) fname ftype Source #

HasUStore mname key value templ => StoreHasSubmap (UStore templ) mname key value Source # 
Instance details

Defined in Lorentz.UStore.Instances

Methods

storeSubmapOps :: StoreSubmapOps (UStore templ) mname key value Source #

SameUStoreTemplate template1 template2 => CanCastTo (UStore template1 :: Type) (UStore template2 :: Type) Source #

We allow casting between UStore_ and UStore freely.

Instance details

Defined in Lorentz.UStore.Migration.Base

Methods

castDummy :: Proxy (UStore template1) -> Proxy (UStore template2) -> () Source #

type Rep (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

type Rep (UStore a) = D1 ('MetaData "UStore" "Lorentz.UStore.Types" "lorentz-0.4.0-4bB2PLHB7038abCZLw1vnA" 'True) (C1 ('MetaCons "UStore" 'PrefixI 'True) (S1 ('MetaSel ('Just "unUStore") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (BigMap ByteString ByteString))))
type Unwrapped (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

type Unwrapped (UStore a) = GUnwrapped (Rep (UStore a))
type TypeDocFieldDescriptions (UStore template) Source # 
Instance details

Defined in Lorentz.UStore.Doc

type TypeDocFieldDescriptions (UStore template) = '[] :: [(Symbol, (Maybe Symbol, [(Symbol, Symbol)]))]
type ToT (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

type GetOpKeyHs (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

type GetOpValHs (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

type UpdOpKeyHs (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

type UpdOpParamsHs (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

type MemOpKeyHs (UStore a) Source # 
Instance details

Defined in Lorentz.UStore.Types

newtype k |~> v Source #

Describes one virtual big map in the storage.

Constructors

UStoreSubMap 

Fields

Instances

Instances details
(Eq k, Eq v) => Eq (k |~> v) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

(==) :: (k |~> v) -> (k |~> v) -> Bool #

(/=) :: (k |~> v) -> (k |~> v) -> Bool #

(Show k, Show v) => Show (k |~> v) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

showsPrec :: Int -> (k |~> v) -> ShowS #

show :: (k |~> v) -> String #

showList :: [k |~> v] -> ShowS #

(Ord k, Arbitrary k, Arbitrary v) => Arbitrary (k |~> v) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

arbitrary :: Gen (k |~> v) #

shrink :: (k |~> v) -> [k |~> v] #

Default (k |~> v) Source # 
Instance details

Defined in Lorentz.UStore.Types

Methods

def :: k |~> v #

newtype UStoreFieldExt (m :: UStoreMarkerType) (v :: Type) Source #

Describes plain field in the storage.

Constructors

UStoreField 

Fields

Instances

Instances details
Eq v => Eq (UStoreFieldExt m v) Source # 
Instance details

Defined in Lorentz.UStore.Types

Show v => Show (UStoreFieldExt m v) Source # 
Instance details

Defined in Lorentz.UStore.Types

Arbitrary v => Arbitrary (UStoreFieldExt m v) Source # 
Instance details

Defined in Lorentz.UStore.Types

type UStoreField = UStoreFieldExt UMarkerPlainField Source #

Just a plain field used as data.

type UStoreMarkerType = UStoreMarker -> Type Source #

Specific kind used to designate markers for UStoreFieldExt.

We suggest that fields may serve different purposes and so annotated with special markers accordingly, which influences translation to Michelson. See example below.

This Haskell kind is implemented like that because we want markers to differ from all other types in kind; herewith UStoreMarkerType is still an open kind (has potentially infinite number of inhabitants).

class KnownUStoreMarker (marker :: UStoreMarkerType) where Source #

Allows to specify format of key under which fields of this type are stored. Useful to avoid collisions.

Minimal complete definition

Nothing

Associated Types

type ShowUStoreField marker v :: ErrorMessage Source #

Display type-level information about UStore field with given marker and field value type. Used for error messages.

type ShowUStoreField marker v = 'Text "field of type " :<>: 'ShowType v Source #

Methods

mkFieldMarkerUKey :: MText -> ByteString Source #

By field name derive key under which field should be stored.

Instances

Instances details
KnownUStoreMarker UMarkerPlainField Source # 
Instance details

Defined in Lorentz.UStore.Types

Type-lookup-by-name

type GetUStoreKey store name = MSKey (GetUStore name store) Source #

Get type of submap key.

type GetUStoreValue store name = MSValue (GetUStore name store) Source #

Get type of submap value.

type GetUStoreField store name = FSValue (GetUStore name store) Source #

Get type of plain field. This ignores marker with field type.

type GetUStoreFieldMarker store name = FSMarker (GetUStore name store) Source #

Get kind of field.

Instructions

ustoreMem :: forall store name s. KeyAccessC store name => Label name -> (GetUStoreKey store name ': (UStore store ': s)) :-> (Bool ': s) Source #

ustoreGet :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name ': (UStore store ': s)) :-> (Maybe (GetUStoreValue store name) ': s) Source #

ustoreUpdate :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name ': (Maybe (GetUStoreValue store name) ': (UStore store ': s))) :-> (UStore store ': s) Source #

ustoreInsert :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name ': (GetUStoreValue store name ': (UStore store ': s))) :-> (UStore store ': s) Source #

ustoreInsertNew :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (forall s0 any. (GetUStoreKey store name ': s0) :-> any) -> (GetUStoreKey store name ': (GetUStoreValue store name ': (UStore store ': s))) :-> (UStore store ': s) Source #

Insert a key-value pair, but fail if it will overwrite some existing entry.

ustoreDelete :: forall store name s. KeyAccessC store name => Label name -> (GetUStoreKey store name ': (UStore store ': s)) :-> (UStore store ': s) Source #

ustoreToField :: forall store name s. FieldAccessC store name => Label name -> (UStore store ': s) :-> (GetUStoreField store name ': s) Source #

Like toField, but for UStore.

This may fail only if UStore was made up incorrectly during contract initialization.

ustoreGetField :: forall store name s. FieldAccessC store name => Label name -> (UStore store ': s) :-> (GetUStoreField store name ': (UStore store ': s)) Source #

Like getField, but for UStore.

This may fail only if UStore was made up incorrectly during contract initialization.

ustoreSetField :: forall store name s. FieldAccessC store name => Label name -> (GetUStoreField store name ': (UStore store ': s)) :-> (UStore store ': s) Source #

Like setField, but for UStore.

Instruction constraints

type HasUStore name key value store = (KeyAccessC store name, ValueAccessC store name, GetUStoreKey store name ~ key, GetUStoreValue store name ~ value) Source #

This constraint can be used if a function needs to work with big store, but needs to know only about some submap(s) of it.

It can use all UStore operations for a particular name, key and value without knowing whole template.

type HasUField name ty store = (FieldAccessC store name, GetUStoreField store name ~ ty) Source #

This constraint can be used if a function needs to work with big store, but needs to know only about some field of it.

type HasUStoreForAllIn store constrained = (Generic store, GHasStoreForAllIn constrained (Rep store)) Source #

Write down all sensisble constraints which given store satisfies and apply them to constrained.

This store should have |~> and UStoreField fields in its immediate fields, no deep inspection is performed.

UStore composability

liftUStore :: (Generic template, RequireAllUniqueFields template) => Label name -> (UStore (GetFieldType template name) ': s) :-> (UStore template ': s) Source #

Lift an UStore to another UStore which contains all the entries of the former under given field.

This function is not intended for use in migrations, only in normal entry points.

Note that this function ensures that template of resulting store does not contain inner nested templates with duplicated fields, otherwise UStore invariants could get broken.

unliftUStore :: Generic template => Label name -> (UStore template ': s) :-> (UStore (GetFieldType template name) ': s) Source #

Unlift an UStore to a smaller UStore which is part of the former.

This function is not intended for use in migrations, only in normal entry points.

Surprisingly, despite smaller UStore may have extra entries, this function is safe when used in contract code. Truly, all getters and setters are still safe to use. Also, there is no way for the resulting small UStore to leak outside of the contract since the only place where big_map can appear is contract storage, so this small UStore can be either dropped or lifted back via liftUStore to appear as part of the new contract's state.

When this function is run as part of standalone instructions sequence, not as part of contract code (e.g. in tests), you may get an UStore with entries not inherent to it.

Documentation

class Typeable template => UStoreTemplateHasDoc template where Source #

Information for UStore template required for documentation.

You only need to instantiate this for templates used directly in UStore, nested subtemplates do not need this instance.

Minimal complete definition

ustoreTemplateDocDescription

Methods

ustoreTemplateDocName :: Text Source #

UStore template name as it appears in documentation.

Should be only 1 word.

ustoreTemplateDocDescription :: Markdown Source #

Description of template.

ustoreTemplateDocContents :: Markdown Source #

Description of template entries.

ustoreTemplateDocDependencies :: [SomeTypeWithDoc] Source #

class KnownUStoreMarker marker => UStoreMarkerHasDoc (marker :: UStoreMarkerType) where Source #

Instantiated for documented UStore markers.

Methods

ustoreMarkerKeyEncoding :: Text -> Text Source #

Specifies key encoding.

You accept description of field name, and should return how is it encoded as key of big_map bytes bytes.

Instances

Instances details
UStoreMarkerHasDoc UMarkerPlainField Source # 
Instance details

Defined in Lorentz.UStore.Doc

UStore management from Haskell

mkUStore :: UStoreTraversable MkUStoreTW template => template -> UStore template Source #

Make UStore from separate big_maps and fields.

ustoreDecompose :: forall template. UStoreTraversable DecomposeUStoreTW template => UStore template -> Either Text (UStoreContent, template) Source #

Decompose UStore into separate big_maps and fields.

Since this function needs to UNPACK content of UStore to actual keys and values, you have to provide UnpackEnv.

Along with resulting value, you get a list of UStore entries which were not recognized as belonging to any submap or field according to UStore's template - this should be empty unless UStore invariants were violated.

ustoreDecomposeFull :: forall template. UStoreTraversable DecomposeUStoreTW template => UStore template -> Either Text template Source #

Like ustoreDecompose, but requires all entries from UStore to be recognized.

fillUStore :: UStoreTraversable FillUStoreTW template => template -> UStoreMigration () template Source #

Make migration script which initializes UStore from scratch.

Migrations

newtype MigrationScript (oldStore :: Type) (newStore :: Type) Source #

Code of migration for UStore.

Invariant: preferably should fit into op size / gas limits (quite obvious). Often this stands for exactly one stage of migration (one Tezos transaction).

Instances

Instances details
CanCastTo (Lambda (UStore ot1) (UStore nt1)) (Lambda (UStore ot2) (UStore nt2)) => CanCastTo (MigrationScript ot1 nt1 :: Type) (MigrationScript ot2 nt2 :: Type) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

Methods

castDummy :: Proxy (MigrationScript ot1 nt1) -> Proxy (MigrationScript ot2 nt2) -> () Source #

Show (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

Methods

showsPrec :: Int -> MigrationScript oldStore newStore -> ShowS #

show :: MigrationScript oldStore newStore -> String #

showList :: [MigrationScript oldStore newStore] -> ShowS #

Generic (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

Associated Types

type Rep (MigrationScript oldStore newStore) :: Type -> Type #

Methods

from :: MigrationScript oldStore newStore -> Rep (MigrationScript oldStore newStore) x #

to :: Rep (MigrationScript oldStore newStore) x -> MigrationScript oldStore newStore #

Wrapped (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

Associated Types

type Unwrapped (MigrationScript oldStore newStore) #

Methods

_Wrapped' :: Iso' (MigrationScript oldStore newStore) (Unwrapped (MigrationScript oldStore newStore)) #

Each '[Typeable :: Type -> Constraint, UStoreTemplateHasDoc] '[oldStore, newStore] => TypeHasDoc (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

Associated Types

type TypeDocFieldDescriptions (MigrationScript oldStore newStore) :: FieldDescriptions #

IsoValue (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

Associated Types

type ToT (MigrationScript oldStore newStore) :: T #

Methods

toVal :: MigrationScript oldStore newStore -> Value (ToT (MigrationScript oldStore newStore)) #

fromVal :: Value (ToT (MigrationScript oldStore newStore)) -> MigrationScript oldStore newStore #

HasTypeAnn (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

Methods

getTypeAnn :: Notes (ToT (MigrationScript oldStore newStore)) Source #

type Rep (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

type Rep (MigrationScript oldStore newStore) = D1 ('MetaData "MigrationScript" "Lorentz.UStore.Migration.Base" "lorentz-0.4.0-4bB2PLHB7038abCZLw1vnA" 'True) (C1 ('MetaCons "MigrationScript" 'PrefixI 'True) (S1 ('MetaSel ('Just "unMigrationScript") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Lambda UStore_ UStore_))))
type Unwrapped (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

type Unwrapped (MigrationScript oldStore newStore) = GUnwrapped (Rep (MigrationScript oldStore newStore))
type TypeDocFieldDescriptions (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

type TypeDocFieldDescriptions (MigrationScript oldStore newStore) = '[] :: [(Symbol, (Maybe Symbol, [(Symbol, Symbol)]))]
type ToT (MigrationScript oldStore newStore) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

type ToT (MigrationScript oldStore newStore) = GValueType (Rep (MigrationScript oldStore newStore))

data UStoreMigration (oldTempl :: Type) (newTempl :: Type) Source #

Keeps information about migration between UStores with two given templates.

Instances

Instances details
MapLorentzInstr (UStoreMigration os ns) Source # 
Instance details

Defined in Lorentz.UStore.Migration.Base

Methods

mapLorentzInstr :: (forall (i :: [Type]) (o :: [Type]). (i :-> o) -> i :-> o) -> UStoreMigration os ns -> UStoreMigration os ns Source #

migrationToScript :: UStoreMigration os ns -> MigrationScript os ns Source #

Get migration script in case of simple (non-batched) migration.

migrationToScriptI :: UStoreMigration os ns -> Identity (MigrationScript os ns) Source #

Get migration script in case of simple (non-batched) migration.

migrationToLambda :: UStoreMigration oldTemplate newTemplate -> Lambda (UStore oldTemplate) (UStore newTemplate) Source #

Turn Migration into a whole piece of code for transforming storage.

This is not want you'd want to use for contract deployment because of gas and operation size limits that Tezos applies to transactions.

mkUStoreMigration :: Lambda (MUStore oldTempl newTempl (BuildDiff oldTempl newTempl) '[]) (MUStore oldTempl newTempl '[] _1) -> UStoreMigration oldTempl newTempl Source #

Safe way to create migration scripts for UStore.

You have to supply a code which would transform MUStore, coverring required diff step-by-step. All basic instructions work, also use migrate* functions from this module to operate with MUStore.

This method produces a whole migration, it cannot be splitted in batches. In case if your migration is too big to be applied within a single transaction, use mkUStoreBatchedMigration.

mustoreToOld :: RequireBeInitial touched => (MUStore oldTemplate newTemplate remDiff touched ': s) :-> (UStore oldTemplate ': s) Source #

Get the old version of storage.

This can be applied only in the beginning of migration.

In fact this function is not very useful, all required operations should be available for MUStore, but leaving it here just in case.

migrateGetField :: forall field oldTempl newTempl diff touched fieldTy s. (HasUField field fieldTy oldTempl, RequireUntouched field (field `IsElem` touched)) => Label field -> (MUStore oldTempl newTempl diff touched ': s) :-> (fieldTy ': (MUStore oldTempl newTempl diff touched ': s)) Source #

Get a field present in old version of UStore.

migrateAddField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcAdd field diff, HasUField field fieldTy newTempl) => Label field -> (fieldTy ': (MUStore oldTempl newTempl diff touched ': s)) :-> (MUStore oldTempl newTempl newDiff (field ': touched) ': s) Source #

Add a field which was not present before. This covers one addition from the diff and any removals of field with given name.

This function cannot overwrite existing field with the same name, if this is necessary use migrateOverwriteField which would declare removal explicitly.

migrateRemoveField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcRemove field diff, HasUField field fieldTy oldTempl) => Label field -> (MUStore oldTempl newTempl diff touched ': s) :-> (MUStore oldTempl newTempl newDiff (field ': touched) ': s) Source #

Remove a field which should not be present in new version of storage. This covers one removal from the diff.

In fact, this action could be performed automatically, but since removal is a destructive operation, being explicit about it seems like a good thing.

migrateExtractField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcRemove field diff, HasUField field fieldTy oldTempl, RequireUntouched field (field `IsElem` touched)) => Label field -> (MUStore oldTempl newTempl diff touched ': s) :-> (fieldTy ': (MUStore oldTempl newTempl newDiff (field ': touched) ': s)) Source #

Get and remove a field from old version of UStore.

You probably want to use this more often than plain migrateRemoveField.

migrateOverwriteField :: forall field oldTempl newTempl diff touched fieldTy oldFieldTy marker oldMarker newDiff newDiff0 s. ('(UStoreFieldExt oldMarker oldFieldTy, newDiff0) ~ CoverDiff 'DcRemove field diff, '(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcAdd field newDiff0, HasUField field fieldTy newTempl) => Label field -> (fieldTy ': (MUStore oldTempl newTempl diff touched ': s)) :-> (MUStore oldTempl newTempl newDiff (field ': touched) ': s) Source #

Remove field and write new one in place of it.

This is semantically equivalent to dip (migrateRemoveField label) >> migrateAddField label, but is cheaper.

migrateModifyField :: forall field oldTempl newTempl diff touched fieldTy s. (HasUField field fieldTy oldTempl, HasUField field fieldTy newTempl) => Label field -> (fieldTy ': (MUStore oldTempl newTempl diff touched ': s)) :-> (MUStore oldTempl newTempl diff touched ': s) Source #

Modify field which should stay in new version of storage. This does not affect remaining diff.

Extras

type PickMarkedFields marker template = GPickMarkedFields marker (Rep template) Source #

Collect all fields with the given marker.

type UStoreTraversable way a = (Generic a, GUStoreTraversable way (Rep a), UStoreTraversalWay way) Source #

Constraint for UStore traversal.