Created
March 23, 2016 20:09
-
-
Save aavogt/d060d45345284a3e3239 to your computer and use it in GitHub Desktop.
overload Map and Set insert
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
| {-# LANGUAGE UndecidableInstances #-} | |
| {-# LANGUAGE FlexibleInstances #-} | |
| {-# LANGUAGE FlexibleContexts #-} | |
| {-# LANGUAGE MultiParamTypeClasses #-} | |
| {-# LANGUAGE TypeFamilies #-} | |
| {-# LANGUAGE ScopedTypeVariables #-} | |
| -- | properly overload M.insert and S.insert | |
| module Insert where | |
| import Data.Proxy | |
| import Data.Set (Set) | |
| import qualified Data.Set as S | |
| import Data.Map (Map) | |
| import qualified Data.Map as M | |
| class Insert1 e where | |
| insert1 :: e | |
| instance Ord e => Insert1 (e -> Set e -> Set e) where | |
| insert1 = S.insert | |
| instance Ord k => Insert1 (k -> v -> Map k v -> Map k v) where | |
| insert1 = M.insert | |
| -- a better way: | |
| class Insert2 pk e where | |
| insert2_ :: Proxy pk -> e -- user calls 'insert2' | |
| type family MkPK x :: * | |
| type instance MkPK (Set e) = Proxy Set | |
| type instance MkPK (Map k v) = Proxy Map | |
| instance (insertSet ~ (e -> Set e -> Set e), Ord e) | |
| => Insert2 (Proxy Set) insertSet where | |
| insert2_ _ = S.insert | |
| instance (insertMap ~ (k -> v -> Map k v -> Map k v), Ord k) | |
| => Insert2 (Proxy Map) insertMap where | |
| insert2_ _ = M.insert | |
| -- | figure out what collection we have | |
| type family GetPK e | |
| type instance GetPK (a -> b -> Set c) = Proxy Set | |
| -- c could be `Map a (Set b) -> Map a (Set b)`, which | |
| -- should make the result type Proxy Map. IE. | |
| -- | |
| -- > insert () S.empty M.empty :: Map () (Set t) | |
| -- type instance GetPK (a -> Set b -> c) = Proxy Set | |
| type instance GetPK (a -> b -> Map c d -> e) = Proxy Map | |
| type instance GetPK (a -> b -> c -> Map d e) = Proxy Map | |
| insert2 :: forall t a b c. (Insert2 (GetPK t) t, t ~ (a -> b -> c)) => t | |
| insert2 = insert2_ (Proxy :: Proxy (GetPK t)) | |
| {- ^ | |
| >>> :t \k -> (insert2 k mempty :: Set ()) | |
| \k -> (insert2 k mempty :: Set ()) :: () -> Set () | |
| compare with | |
| >>> :t \k -> insert1 k mempty :: Set () | |
| \k -> insert1 k mempty :: Set () | |
| :: (Monoid a, Insert1 (t -> a -> Set ())) => t -> Set () | |
| -} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment