| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Data.Record.Linear.Borrow.Experimental.PatternMatch
Description
An experimental module for splitting a borrow of a record by pattern matching on it. If you want to split out a field gradually and partially, see also Data.Record.Linear.Borrow.Experimental.Split.
The API is subject to future change.
Synopsis
- type RecordLabel a (f :: Symbol) v = RecordLabel' a '(f, v)
- (.#) :: forall (bk :: BorrowKind) (α :: Lifetime) a (field :: Symbol) val. Borrow bk α a %1 -> RecordLabel a field val %1 -> Borrow bk α val
- (.@) :: forall elim a (bk :: BorrowKind) (α :: Lifetime). RecordEliminator elim a => Borrow bk α a %1 -> elim %1 -> SplitBorrow elim bk α a
- type RecordLabels a (fs :: [(Symbol, Type)]) = LabelsOrBorrows ('RecordLabelOf a) fs
- type FieldBorrows (bk :: BorrowKind) (α :: Lifetime) (fs :: [(Symbol, Type)]) = LabelsOrBorrows ('BorrowOf bk α) fs
- data LabelsOrBorrows (h :: Fun) (xs :: [(Symbol, Type)]) where
- RNil :: forall (h :: Fun). LabelsOrBorrows h ('[] :: [(Symbol, Type)])
- (:#-) :: forall (h :: Fun) (k :: Symbol) v (xs1 :: [(Symbol, Type)]). Apply h '(k, v) -> LabelsOrBorrows h xs1 -> LabelsOrBorrows h ('(k, v) ': xs1)
- class RecordEliminator elim a where
- type SplitBorrow elim (bk :: BorrowKind) (α :: Lifetime) a
- splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). elim %1 -> Borrow bk α a %1 -> SplitBorrow elim bk α a
- data RecordLabel' (r :: TYPE rep) (fldVal :: (Symbol, Type)) where
- RecLab :: forall (field :: Symbol) r1 a. HasField field r1 a => RecordLabel' r1 '(field, a)
Label Type
type RecordLabel a (f :: Symbol) v = RecordLabel' a '(f, v) Source #
witnesses that the record type RecordLabel r f ar has a field named f of type a.
Intended to be constructed with OverloadedLabels extension, so that you can construct it by #f syntax when the field f of a is imported in the current scope.
You can also expose RecordLabel only, so that you can allow users to access such fields while internal implementation unexposed.
Single Field Accessor
(.#) :: forall (bk :: BorrowKind) (α :: Lifetime) a (field :: Symbol) val. Borrow bk α a %1 -> RecordLabel a field val %1 -> Borrow bk α val Source #
recBor divides a record borrow .# #frecBor into a borrow of the field f.
This is (.@) specialised to RecordLabel for better type inference.
To access multiple fields, you can use (.@) with a tuple of RecordLabels or RecordLabels.
See Splitting a record borrow into pieces for more details.
Splitting a record borrow into pieces
Overview
(.#) is handy when you need only one field of a borrowed record, but not applicable when you need to access more than one fields.
For that purpose, we provide (.@) operator for splitting a borrow of a record into FieldBorrows of its fields.
Consider the following:
>>>import Data.Ref.Linear (Ref)>>>import Data.Vector.Mutable.Linear.Borrow (Vector)>>>import Control.Monad.Borrow.Pure.BO>>>data MyRecord = MyRecord { int :: Ref Int, strs :: Vector String, bool :: Ref Bool }
Suppose we have a mutable borrow of some MyRecord:
>>>:{mutRec :: Mut α (MyRecord) mutRec = undefined :}
So, let's divide the mutable borrow into several pieces with (.@).
First, we need to enable OverloadedLabels extension to construct RecordLabels:
>>>:set -XOverloadedLabels
First, we just want to divide into all the fields, in arbitrary order:
>>>(mutStrs, mutBool, mutInt) = mutRec .@ (#strs, #bool, #int)>>>:t mutStrsmutStrs :: Borrow 'Mut α (Vector String)
>>>:t mutBoolmutBool :: Borrow 'Mut α (Ref Bool)
>>>:t mutIntmutInt :: Borrow 'Mut α (Ref Int)
Or, we can just divide into some of the fields (say, bool and strs):
>>>(mutStrs, mutBool) = mutRec .@ (#strs, #bool)>>>:t mutStrsmutStrs :: Borrow 'Mut α (Vector String)
>>>:t mutBoolmutBool :: Borrow 'Mut α (Ref Bool)
Specifying the same field more than once results in a type error:
mutRec .@ (#strs, #bool, #strs) -- error: Split record fields must be distinct, but got duplicate field: "strs"
In genral, (.@) accepts any eliminator of a record borrow, which is typically one of the following:
- A tuple of
RecordLabels without duplcations (currently 2 to 5 components), or - A heterogeneous list
RecordLabelsofRecordLabels, constructed with(:#-)andRNil, without duplcations on fields.
And fields not listed within the eliminator are not accessible after the split.
The examples so far uses tuples as eliminators, but you can also use RecordLabels as follows:
>>>mutStrs :#- mutBool :#- RNil = mutRec .@ #strs :#- #bool :#- RNil
RecordLabels will be mapped to FieldBorrows after the split, and you can also use (:#-) and RNil for pattern-matching.
Indeed, RecordLabel itself is also a RecordEliminator, but if you are using `#f` syntax for constructing RecordLabel, you cannot use it with .@ operator without type annotation because of the ambiguity.
If you just want to access one field, you can use (.#) operator.
APIs
(.@) :: forall elim a (bk :: BorrowKind) (α :: Lifetime). RecordEliminator elim a => Borrow bk α a %1 -> elim %1 -> SplitBorrow elim bk α a infixl 4 Source #
Divides a borrow of a record into multiple FieldBorrows of its fields, according to the given eliminator.
Typically, elim is one of the following:
A tuple of
RecordLabels without duplcations (currently 2 to 5 components):(.@) :: a %1 -> (
RecordLabela f1 v1,RecordLabela f2 v2,RecordLabela f3 v3) %1 -> (Borrowbk α v1,Borrowbk α v2,Borrowbk α v3)A heterogeneous list of
RecordLabels without duplications:(.@) :: a %1 ->
RecordLabels'[ '(f1, v1), '(f2, v2), '(f3, v3), .. ] %1 ->FieldBorrows'[ '(f1, v1), '(f2, v2), '(f3, v3) ]
type RecordLabels a (fs :: [(Symbol, Type)]) = LabelsOrBorrows ('RecordLabelOf a) fs Source #
type FieldBorrows (bk :: BorrowKind) (α :: Lifetime) (fs :: [(Symbol, Type)]) = LabelsOrBorrows ('BorrowOf bk α) fs Source #
Heterogeneous FieldBorrows. If the record type a is clear from the context, you can construct it with '(:#-)' and RNil with OverloadedLabels extension:
data MyRecord = MyRecord { foo :: Int, bar :: String, buz :: Bool }
mutRec :: Mut α MyRecord
mutRec = ...
buzMut :#- fooMut :#- RNil = mutRec .@ #buz :#- #foo :#- RNil
data LabelsOrBorrows (h :: Fun) (xs :: [(Symbol, Type)]) where Source #
Constructors
| RNil :: forall (h :: Fun). LabelsOrBorrows h ('[] :: [(Symbol, Type)]) | |
| (:#-) :: forall (h :: Fun) (k :: Symbol) v (xs1 :: [(Symbol, Type)]). Apply h '(k, v) -> LabelsOrBorrows h xs1 -> LabelsOrBorrows h ('(k, v) ': xs1) infixr 5 |
Instances
| Consumable (LabelsOrBorrows h xs) Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods consume :: LabelsOrBorrows h xs %1 -> () # | |
| Affine (LabelsOrBorrows h xs) Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods aff :: LabelsOrBorrows h xs %1 -> Aff (LabelsOrBorrows h xs) Source # | |
| (IsUnique fvs, label ~ 'RecordLabelOf a) => RecordEliminator (LabelsOrBorrows label fvs) a Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). LabelsOrBorrows label fvs %1 -> Borrow bk α a %1 -> SplitBorrow (LabelsOrBorrows label fvs) bk α a Source # | |
| type SplitBorrow (LabelsOrBorrows label fvs) bk α a Source # | |
Internal APIs
class RecordEliminator elim a where Source #
A class for *eliminators* of record, which can split a borrow of the whole record into FieldBorrows of its fields.
Typically, an eliminator is a tuple of RecordLabels or heterogeneous RecordLabels.
Associated Types
type SplitBorrow elim (bk :: BorrowKind) (α :: Lifetime) a Source #
Methods
splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). elim %1 -> Borrow bk α a %1 -> SplitBorrow elim bk α a Source #
Instances
| (IsUnique fvs, label ~ 'RecordLabelOf a) => RecordEliminator (LabelsOrBorrows label fvs) a Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). LabelsOrBorrows label fvs %1 -> Borrow bk α a %1 -> SplitBorrow (LabelsOrBorrows label fvs) bk α a Source # | |
| (IsRecordLabel' a l f1 v1, IsRecordLabel' a r f2 v2, Distinct f1 f2) => RecordEliminator (l, r) a Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). (l, r) %1 -> Borrow bk α a %1 -> SplitBorrow (l, r) bk α a Source # | |
| a ~ r => RecordEliminator (RecordLabel' r '(field, val)) a Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). RecordLabel' r '(field, val) %1 -> Borrow bk α a %1 -> SplitBorrow (RecordLabel' r '(field, val)) bk α a Source # | |
| (IsRecordLabel' a l1 f1 v1, IsRecordLabel' a l2 f2 v2, IsRecordLabel' a l3 f3 v3, Distinct f1 f2, Distinct f1 f3, Distinct f2 f3) => RecordEliminator (l1, l2, l3) a Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). (l1, l2, l3) %1 -> Borrow bk α a %1 -> SplitBorrow (l1, l2, l3) bk α a Source # | |
| (IsRecordLabel' a l1 f1 v1, IsRecordLabel' a l2 f2 v2, IsRecordLabel' a l3 f3 v3, IsRecordLabel' a l4 f4 v4, Distinct f1 f2, Distinct f1 f3, Distinct f1 f4, Distinct f2 f3, Distinct f2 f4, Distinct f3 f4) => RecordEliminator (l1, l2, l3, l4) a Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). (l1, l2, l3, l4) %1 -> Borrow bk α a %1 -> SplitBorrow (l1, l2, l3, l4) bk α a Source # | |
| (IsRecordLabel' a l1 f1 v1, IsRecordLabel' a l2 f2 v2, IsRecordLabel' a l3 f3 v3, IsRecordLabel' a l4 f4 v4, IsRecordLabel' a l5 f5 v5, Distinct f1 f2, Distinct f1 f3, Distinct f1 f4, Distinct f1 f5, Distinct f2 f3, Distinct f2 f4, Distinct f2 f5, Distinct f3 f4, Distinct f3 f5, Distinct f4 f5) => RecordEliminator (l1, l2, l3, l4, l5) a Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). (l1, l2, l3, l4, l5) %1 -> Borrow bk α a %1 -> SplitBorrow (l1, l2, l3, l4, l5) bk α a Source # | |
data RecordLabel' (r :: TYPE rep) (fldVal :: (Symbol, Type)) where Source #
The actual definition of RecordLabel for type-level hacks.
Constructors
| RecLab :: forall (field :: Symbol) r1 a. HasField field r1 a => RecordLabel' r1 '(field, a) |
Instances
| (HasField field r a, fldVal ~ '(field, a)) => IsLabel field (RecordLabel' r fldVal) Source # | This allows users to use |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods fromLabel :: RecordLabel' r fldVal # | |
| KnownSymbol field => Show (RecordLabel' r '(field, a)) Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods showsPrec :: Int -> RecordLabel' r '(field, a) -> ShowS # show :: RecordLabel' r '(field, a) -> String # showList :: [RecordLabel' r '(field, a)] -> ShowS # | |
| a ~ r => RecordEliminator (RecordLabel' r '(field, val)) a Source # | |
Defined in Data.Record.Linear.Borrow.Experimental.PatternMatch Methods splitRecord :: forall (bk :: BorrowKind) (α :: Lifetime). RecordLabel' r '(field, val) %1 -> Borrow bk α a %1 -> SplitBorrow (RecordLabel' r '(field, val)) bk α a Source # | |
| type SplitBorrow (RecordLabel' r '(field, val)) bk α a Source # | |