Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factor out SOAS and prepare unification modules #4

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions free-foil-hou.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,20 @@ custom-setup

library
exposed-modules:
Data.SOAS
Language.Lambda.Impl
Language.Lambda.Syntax.Abs
Language.Lambda.Syntax.Layout
Language.Lambda.Syntax.Lex
Language.Lambda.Syntax.Par
Language.Lambda.Syntax.Print
Runner.Impl
other-modules:
Paths_free_foil_hou
autogen-modules:
Paths_free_foil_hou
hs-source-dirs:
src
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
build-tools:
alex >=3.2.4
, happy >=1.19.9
Expand All @@ -68,7 +68,7 @@ executable free-foil-hou-exe
Paths_free_foil_hou
hs-source-dirs:
app
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
build-tools:
alex >=3.2.4
, happy >=1.19.9
Expand All @@ -95,7 +95,7 @@ test-suite free-foil-hou-test
Paths_free_foil_hou
hs-source-dirs:
test
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
build-tools:
alex >=3.2.4
, happy >=1.19.9
Expand Down
1 change: 0 additions & 1 deletion package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ ghc-options:
- -Widentities
- -Wincomplete-record-updates
- -Wincomplete-uni-patterns
- -Wmissing-export-lists
- -Wmissing-home-modules
- -Wpartial-fields
- -Wredundant-constraints
Expand Down
111 changes: 111 additions & 0 deletions src/Data/SOAS.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
module Data.SOAS where

import qualified Control.Monad.Foil as Foil
import Data.Bifunctor
import Data.Bifunctor.Sum
import Data.Bifunctor.TH
import Generics.Kind.TH (deriveGenericK)
import qualified GHC.Generics as GHC

import Control.Monad.Free.Foil
import Data.ZipMatchK

data MetaAppSig metavar scope term = MetaAppSig metavar [term]
deriving (Functor, Foldable, Traversable, GHC.Generic)

deriveBifunctor ''MetaAppSig
deriveBifoldable ''MetaAppSig
deriveBitraversable ''MetaAppSig

deriveGenericK ''MetaAppSig

instance ZipMatchK a => ZipMatchK (MetaAppSig a)

-- >>> a = "λy.(λx.λy.X[x, y X[y, x]])y" :: MetaTerm Raw.MetaVarIdent Foil.VoidS
-- >>> b = "λz.(λx.λy.X[x, y X[y, x]])z" :: MetaTerm Raw.MetaVarIdent Foil.VoidS
-- >>> alphaEquiv Foil.emptyScope a b
-- True

pattern MetaApp :: metavar -> [AST binder (Sum p (MetaAppSig metavar)) n] -> AST binder (Sum p (MetaAppSig metavar)) n
pattern MetaApp metavar args = Node (R2 (MetaAppSig metavar args))

type SOAS binder metavar sig n = AST binder (Sum sig (MetaAppSig metavar)) n

data MetaAbs binder sig where
MetaAbs :: Foil.NameBinderList Foil.VoidS n -> AST binder sig n -> MetaAbs binder sig

newtype MetaSubst binder sig metavar metavar' = MetaSubst {getMetaSubst :: (metavar, MetaAbs binder (Sum sig (MetaAppSig metavar')))}

newtype MetaSubsts binder sig metavar metavar' = MetaSubsts
{ getSubsts :: [MetaSubst binder sig metavar metavar']
}

-- M[g, \z. z a]
-- M[x, y] -> y x
-- y = \z. z a
-- x = g
-- (\z. z a) g

-- >>> subst = "X [x0, x1] ↦ x1 x0" :: MetaSubst TermSig Raw.MetaVarIdent Raw.MetaVarIdent
-- >>> term = "λg. λa. λw. X[g, λz. z a]"
-- >>> nfMetaTermWithEmptyScope $ applyMetaSubsts id Foil.emptyScope (MetaSubsts [subst]) term
-- λ x0 . λ x1 . λ x2 . x0 x1
-- >>> subst = "X [x, y] ↦ (λ z . y z) x" :: MetaSubst TermSig Raw.MetaVarIdent Raw.MetaVarIdent
-- >>> term = "λg. λa. λw. X[g, λz. z a]"
-- >>> nfMetaTermWithEmptyScope $ applyMetaSubsts id Foil.emptyScope (MetaSubsts [subst]) term
-- λ x0 . λ x1 . λ x2 . x0 x1
-- >>> term = "λg. λa. X[g, λz. z a]"
-- >>> nfMetaTermWithEmptyScope $ applyMetaSubsts id Foil.emptyScope (MetaSubsts [subst]) term
-- λ x0 . λ x1 . x0 x1
applyMetaSubsts ::
(Bifunctor sig, Eq metavar, Bifunctor (MetaAppSig metavar'), Foil.Distinct n, Foil.CoSinkable binder, Foil.SinkableK binder) =>
(metavar -> metavar') ->
Foil.Scope n ->
MetaSubsts binder sig metavar metavar' ->
SOAS binder metavar sig n ->
SOAS binder metavar' sig n
applyMetaSubsts rename scope substs = \case
Var x -> Var x
Node (R2 (MetaAppSig metavar args)) ->
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Node (R2 (MetaAppSig metavar args)) ->
MetaApp metavar args ->

let args' = map apply args
in case lookup metavar (getMetaSubst <$> getSubsts substs) of
Just (MetaAbs names body) ->
let substs' =
Foil.nameMapToSubstitution $
toNameMap Foil.emptyNameMap names args'
in substitute scope substs' body
Nothing -> Node $ R2 $ MetaAppSig (rename metavar) args'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Nothing -> Node $ R2 $ MetaAppSig (rename metavar) args'
Nothing -> MetaApp (rename metavar) args'

Node (L2 term) -> Node $ L2 $ bimap (goScopedAST rename scope substs) apply term
where
apply = applyMetaSubsts rename scope substs

toNameMap :: Foil.NameMap n a -> Foil.NameBinderList n l -> [a] -> Foil.NameMap l a
toNameMap nameMap Foil.NameBinderListEmpty [] = nameMap
toNameMap nameMap (Foil.NameBinderListCons binder rest) (x : xs) = toNameMap fresh rest xs
where
fresh = Foil.addNameBinder binder x nameMap
toNameMap _ _ _ = error "mismatched name list and argument list"

goScopedAST ::
(Bifunctor sig, Eq metavar, Bifunctor (MetaAppSig metavar'), Foil.Distinct n, Foil.CoSinkable binder, Foil.SinkableK binder) =>
(metavar -> metavar') ->
Foil.Scope n ->
MetaSubsts binder sig metavar metavar' ->
ScopedAST binder (Sum sig (MetaAppSig metavar)) n ->
ScopedAST binder (Sum sig (MetaAppSig metavar')) n
goScopedAST rename' scope' substs' (ScopedAST binder body) =
case Foil.assertDistinct binder of
Foil.Distinct ->
ScopedAST binder (applyMetaSubsts rename' newScope substs' body)
where
newScope = Foil.extendScopePattern binder scope'
Loading