{-# LANGUAGE MultiParamTypeClasses
, FunctionalDependencies
, FlexibleInstances
, UndecidableInstances
, ScopedTypeVariables
, PatternSignatures #-}{-
Map.hs
Copyright 2008 Matthew Sackman <matthew@wellquite.org>
This file is part of Session Types for Haskell.
Session Types for Haskell is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Session Types for Haskell is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Session Types for Haskell.
If not, see <http://www.gnu.org/licenses/>.
-}-- | Heterogeneous maps at the type level. Obviously equality is done-- on types and not values. Duplicate keys are not permitted, as you'd expect.moduleControl.Concurrent.Session.Base.Map(TyMap(..),emptyMap,MapInsert(..),MapLookup(..),MapUpdate(..),MapSize(..),tyMapKeys,MapDelete(..))whereimportControl.Concurrent.Session.Base.NumberimportControl.Concurrent.Session.Base.ListimportControl.Concurrent.Session.Base.BooldataTyMapkeyToIdxidxToValue=TMkeyToIdxidxToValuederiving(Show)emptyMap::TyMapNilNilemptyMap=TMnilnil-- | Insert into a map. Remember, the values are irrelevant, it's only-- the types that matter. Inserting a key that already exists is not-- permitted.classMapInsertm1keyvalm2|m1keyval->m2wheremapInsert::key->val->m1->m2instance(TyListMemberkeyToIdxkeyres,MapInsert'res(TyMapkeyToIdxidxToValue)keyval(TyMapkeyToIdx'idxToValue'),MapDelete(TyMapkeyToIdx'idxToValue')key(TyMapkeyToIdxidxToValue))=>MapInsert(TyMapkeyToIdxidxToValue)keyval(TyMapkeyToIdx'idxToValue')wheremapInsertkeyvalm1@(TMkeyToIdx_)=mapInsert'reskeyvalm1whereres=isTyListMemberkeykeyToIdxclassMapInsert'boolm1keyvalm2|boolm1keyval->m2wheremapInsert'::bool->key->val->m1->m2{-
instance ( TyListUpdateVar idxToValue idx value idxToValue'
, TyListElem keyToIdx key idx
) =>
MapInsert' True (TyMap keyToIdx idxToValue) key value (TyMap keyToIdx idxToValue') where
mapInsert' _ key value (TM keyToIdx idxToValue)
= TM keyToIdx idxToValue'
where
idx = tyListElem keyToIdx key
idxToValue' = tyListUpdateVar idxToValue idx value
-}instance(TyListLengthkeyToIdxnewIdx,TyListReversekeyToIdxkeyToIdxRev,TyListReverse(ConskeykeyToIdxRev)keyToIdx',TyListUpdateVaridxToValuenewIdxvalueidxToValue',TyListkeyToIdxRev,MapDelete(TyMapkeyToIdx'idxToValue')key(TyMapkeyToIdxidxToValue))=>MapInsert'False(TyMapkeyToIdxidxToValue)keyvalue(TyMapkeyToIdx'idxToValue')wheremapInsert'_keyvalue(TMkeyToIdxidxToValue)=TMkeyToIdx'idxToValue'wherekeyToIdx'=tyListReverse.conskey.tyListReverse$keyToIdxidxToValue'=tyListUpdateVaridxToValue(tyListLengthkeyToIdx)value{-
instance ( TyListReverse keyToIdx keyToIdxRev
, TyListReverse idxToValue idxToValueRev
, TyListReverse (Cons key keyToIdxRev) keyToIdx'
, TyListReverse (Cons val idxToValueRev) idxToValue'
, TyList keyToIdxRev
, TyList idxToValueRev
, MapDelete (TyMap keyToIdx' idxToValue') key (TyMap keyToIdx idxToValue)
) =>
MapInsert (TyMap keyToIdx idxToValue) key val (TyMap keyToIdx' idxToValue') where
mapInsert = undefined
-}-- | lookup in a map. Will call fail in Monad if it's not there.classMapLookupmpkeyval|mpkey->valwheremapLookup::mp->key->valinstance(TyListElemkeyToIdxkeyidx,TyListIndexidxToValueidxval)=>MapLookup(TyMapkeyToIdxidxToValue)keyvalwheremapLookup(TMkeyToIdxidxToValue)key=tyListIndexidxToValue$tyListElemkeyToIdxkey-- | Update a map. The key must already be in the map. The value is-- the type of the value, if you see what I mean and so obviously,-- updating the map means changing the type of the value.classMapUpdatempkeyval'mp'|mpkeyval'->mp'wheremapUpdate::mp->key->val'->mp'instance(TyListUpdateVaridxToValueidxval'idxToValue',TyListElemkeyToIdxkeyidx,MapLookup(TyMapkeyToIdxidxToValue')keyval')=>MapUpdate(TyMapkeyToIdxidxToValue)keyval'(TyMapkeyToIdxidxToValue')wheremapUpdate(TMkeyToIdxidxToValue)keyval'=TMkeyToIdx.tyListUpdateVaridxToValue(tyListElemkeyToIdxkey)$val'-- | Find the size of a map.classMapSizempsize|mp->sizewheremapSize::mp->sizeinstance(TyListLengthkeyToIdxlen)=>MapSize(TyMapkeyToIdxidxToValue)lenwheremapSize(TMkeyToIdx_)=tyListLengthkeyToIdxtyMapKeys::TyMapkeyToIdxidxToValue->keyToIdxtyMapKeys(TMkeyToIdx_)=keyToIdxclassMapDeletempkeymp'|mpkey->mp'wheremapDelete::mp->key->mp'instance(TyListElemkeyToIdxkeyidx,TyListTakeidxkeyToIdxkeyToIdxPrefix,TyListTakeidxidxToValueidxToValuePrefix,TyListDropidxPkeyToIdxkeyToIdxSuffix,TyListDropidxPidxToValueidxToValueSuffix,SuccidxidxP,PredidxPidx,TyListAppendkeyToIdxPrefixkeyToIdxSuffixkeyToIdx',TyListAppendidxToValuePrefixidxToValueSuffixidxToValue')=>MapDelete(TyMapkeyToIdxidxToValue)key(TyMapkeyToIdx'idxToValue')wheremapDelete(TMkeyToIdxidxToValue)key=TM(tyListAppendkeyToIdxPrefixkeyToIdxSuffix)(tyListAppendidxToValuePrefixidxToValueSuffix)whereidx=tyListElemkeyToIdxkeyidxP=tySuccidxkeyToIdxPrefix=tyListTakeidxkeyToIdxkeyToIdxSuffix=tyListDropidxPkeyToIdxidxToValuePrefix=tyListTakeidxidxToValueidxToValueSuffix=tyListDropidxPidxToValue