Philipp Zander
-- MainExpand.hs
data AppError =
  InvalidKey Integer | SomeOtherProblems
  deriving (Show)
-- | Validate key and map and potentially return an appropriate AppError.
validateMapKey ::
  Integer              ->
  M.Map Integer String ->
  Maybe AppError
validateMapKey key map =
  case M.member key map of
    False -> Nothing
    True  -> Just $ InvalidKey key
processMapKey ::
  Integer              ->
  M.Map Integer String ->
  String
processMapKey key map =
  case validateMapKey key map of
    Just appError -> "Error: " <> show appError
    Nothing       ->
      case M.lookup key map of
        Nothing -> error "impossible because we just applied validateMapKey"
        Just result -> result-- MainFirst.hs
validateMapKey ::
  Named keyName Integer              ->
  Named mapName (Map Integer String) ->
  Either AppError (Member keyName mapName)
validateMapKey key map =
  case member key map of
    Just proof -> Right proof
    Nothing    -> Left $ InvalidKey (forgetName key)
processMapKey ::
  Integer            ->
  Map Integer String ->
  String
processMapKey key map =
  let
    keyNamed :: Named keyName Integer
    keyNamed = name key
    mapNamed :: Named mapName (Map Integer String)
    mapNamed = name map
  in case validateMapKey keyNamed mapNamed of
    Left appError -> "Error: " <> show appError
    Right proof   -> lookup keyNamed mapNamed proof-- MainFirst.hs
validateMapKey ::
  Named keyName Integer              ->
  Named mapName (Map Integer String) ->
  Either AppError (Member keyName mapName)
validateMapKey key map =
  case member key map of
    Just proof -> Right proof
    Nothing    -> Left $ InvalidKey (forgetName key)
processMapKey ::
  Integer            ->
  Map Integer String ->
  String
processMapKey key map =
  let
    zeroNamed :: Named zeroName Integer
    zeroNamed = name 0
    keyNamed  :: Named keyName Integer
    keyNamed  = name key
    mapNamed  :: Named mapName (Map Integer String)
    mapNamed  = name map
  in case validateMapKey zeroNamed mapNamed of
    Left appError -> "Error: " <> show appError
    Right proof   -> lookup keyNamed mapNamed proofillTyped :: [variable1] -> ([Bool], [variable2])
illTyped aList =
  let
    boolList :: [Bool]
    boolList = aList
    bList   :: [variable2]
    bList   = aList
  in (boolList, bList)    • Couldn't match type ‘variable1’ with ‘Bool’
   |
42 |     boolList = aList
   |                ^^^^^
    • Couldn't match type ‘variable2’ with ‘variable1’
   |
44 |     bList = aList
   |             ^^^^^-- MainFirst.hs
validateMapKey ::
  Named keyName Integer              ->
  Named mapName (Map Integer String) ->
  Either AppError (Member keyName mapName)
validateMapKey key map =
  case member key map of
    Just proof -> Right proof
    Nothing    -> Left $ InvalidKey (forgetName key)
processMapKey ::
  Integer            ->
  Map Integer String ->
  String
processMapKey key map =
  let
    zeroNamed :: Named zeroName Integer
    zeroNamed = name 0
    keyNamed  :: Named keyName Integer
    keyNamed  = name key
    mapNamed  :: Named mapName (Map Integer String)
    mapNamed  = name map
  in case validateMapKey zeroNamed mapNamed of
    Left appError -> "Error: " <> show appError
    Right proof   -> lookup keyNamed mapNamed proof-- Main.hs
processMapKey ::
  Integer            ->
  Map Integer String ->
  String
processMapKey key map =
  name key $ \(keyNamed :: Named keyName Integer)              ->
  name map $ \(mapNamed :: Named mapName (Map Integer String)) ->
  case validateMapKey keyNamed mapNamed of
    Left appError -> "Error: " <> show appError
    Right proof   -> lookup keyNamed mapNamed proof-- Main.hs
processMapKey ::
  Integer            ->
  Map Integer String ->
  String
processMapKey key map =
  name 0   $ \zeroNamed ->
  name key $ \keyNamed  ->
  name map $ \mapNamed  ->
  case validateMapKey zeroNamed mapNamed of
    Left appError -> "Error: " <> show appError
    Right proof   -> lookup keyNamed mapNamed proof    • Couldn't match type ‘name1’ with ‘name’
      Expected type: Member name1 name2
        Actual type: Member name name2
   |
37 |     Right proof -> lookup keyNamed mapNamed proof
   |                                             ^^^^^-- MapWithProofs.hs
insert ::
  (Ord key)                       =>
  Named keyName key               ->
  value                           ->
  Named mapName (M.Map key value) ->
  (forall resultName. InsertResult keyName key value mapName resultName -> r) ->
  r
type InsertResult keyName key value mapName resultName =
  (
    Named resultName (M.Map key value),
    Member keyName resultName,
    mapName `KeySubset` resultName
  )
data map1 `KeySubset` map2 = KeySubset-- Main.hs
insertExample :: String
insertExample =
  name 0                   $ \key0                             ->
  name 1                   $ \key1                             ->
  name (M.singleton 0 "a") $ \mapOld                           ->
  insert key1 "b" mapOld   $ \(mapNew, _proofKey, proofSubset) ->
  case member key0 mapOld of
    Nothing    -> error "impossible because `0` is member of `M.singleton 0 a`"
    Just proof -> lookup key0 mapNew (keySubset proofSubset proof)-- MapWithProofs.hs
keySubset ::
  Either
    ((map1 `KeySubset` map2, Member key map1) -> Void)
    (Member key map2)((S ∧ M) ⇒ ⊥) ∨ N
-- Main.hs
myKeySubset ::
  map1 `KeySubset` map2 ->
  Member key map1       ->
  Member key map2
myKeySubset proof1 proof2 =
  case keySubset of
    Right proof      -> proof
    Left implication -> absurd $ implication (proof1, proof2)S ⇒ (M ⇒ N)
-- Named.hs
{-# language RankNTypes #-}
name ::
  a                                     ->
  (forall name. Named name a -> result) ->
  result
name a continuation = continuation (Named a)-- Main.hs
insertExample :: String
insertExample =
  name 0                   $ \key0                             ->
  name 1                   $ \key1                             ->
  name (M.singleton 0 "a") $ \mapOld                           ->
  insert key1 "b" mapOld   $ \(mapNew, _proofKey, proofSubset) ->
  case member key0 mapOld of
    Nothing    -> error "impossible because `0` is member of `M.singleton 0 a`"
    Just proof -> lookup key0 mapNew (keySubset proofSubset proof)exists keyword that syntactically works like forall [2]https://ocharles.org.uk/blog/posts/2019-08-09-who-authorized-these-ghosts.html contains a great example demonstrating the Curry–Howard isomorphism well and using the technique to avoid redundant checks
[1] Richard Eisenberg. 2020. Richard eisenberg on simplifying constraint solving in ghc. Retrieved February 18, 2021 from https://www.youtube.com/watch?v=flwz6V5Ps8w&t=3m41s
[2] Richard Eisenberg. 2021. Update on dependent haskell. Retrieved February 18, 2021 from https://www.youtube.com/watch?v=TXDivoj1v6w&t=5m17s
[3] Matt Noonan. 2018. Ghosts of departed proofs (functional pearl). In Proceedings of the 11th acm sigplan international symposium on haskell (Haskell 2018), Association for Computing Machinery, New York, NY, USA, 119–131. DOI:https://doi.org/10.1145/3242744.3242755