Skip to content

Commit 0a184d4

Browse files
committed
Add transformation of nameless to named term and generator for nameless terms
1 parent d078b3c commit 0a184d4

File tree

4 files changed

+60
-41
lines changed

4 files changed

+60
-41
lines changed

src/Generator.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ generateNamelessTerm (NamelessVariable var) = show var
1414
generateNamelessTerm (NamelessApplication lhs rhs) = concatMap (\term -> case term of
1515
var@(NamelessVariable _) -> generateNamelessTerm var
1616
_ -> '(':generateNamelessTerm term ++ [')']) [lhs, rhs]
17-
generateNamelessTerm (NamelessAbstraction depth body) = 'λ':generateNamelessTerm body
17+
generateNamelessTerm (NamelessAbstraction body) = 'λ':generateNamelessTerm body

src/Main.hs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
module Main where
22

3-
import Prelude hiding (lookup)
4-
import System.IO (hSetBuffering, stdout, BufferMode (BlockBuffering))
5-
import Parser (parseTerm, Term (Variable))
6-
import Substitution.Named (substitute)
7-
import Generator (generateTerm, generateNamelessTerm)
8-
import Transformer (toNameless)
93
import Data.Map (empty, lookup)
4+
import Generator (generateNamelessTerm, generateTerm)
5+
import Parser (Term (Variable), parseTerm)
6+
import Substitution.Named (substitute)
107
import Substitution.Nameless (substituteNameless)
8+
import System.IO (BufferMode (BlockBuffering), hSetBuffering, stdout)
9+
import Transformer (toNamed, toNameless)
10+
import Prelude hiding (lookup)
1111

1212
main :: IO ()
1313
main = do
1414
hSetBuffering stdout $ BlockBuffering $ Just 1
1515
term <- putStr "Input term: " >> getLine
1616
var <- putStr "Input variable to substitute: " >> getLine -- not using getChr intentionally
17-
if length var /= 1
18-
then error "please provide valid variable"
19-
else do
20-
let (namelessTerm, context) = toNameless (parseTerm term) 0 [] empty
21-
substituteVariable = head var `lookup` context
22-
case substituteVariable of
23-
Nothing -> error "please provide valid variable"
24-
Just index -> do
25-
substituteTerm <- putStr "Input substitution term: " >> getLine
26-
let (substituteNamelessTerm, _) = toNameless (parseTerm substituteTerm) 0 [] context
27-
putStrLn $ generateNamelessTerm $ substituteNameless namelessTerm index substituteNamelessTerm
17+
if length var /= 1
18+
then error "please provide valid variable"
19+
else do
20+
let (namelessTerm, context) = toNameless $ parseTerm term
21+
substituteVariable = head var `lookup` context
22+
substituteTerm <- putStr "Input substitution term: " >> getLine
23+
case substituteVariable of
24+
Nothing -> putStrLn term
25+
Just index ->
26+
let (substituteNamelessTerm, updatedContext) = toNameless $ parseTerm substituteTerm
27+
in putStrLn $ generateTerm $ toNamed (substituteNameless namelessTerm index substituteNamelessTerm) updatedContext
2828

29-
-- let substituteVariable = head var
30-
-- substituteTerm <- putStr "Input substitution term: " >> getLine
31-
-- putStrLn $ generateTerm $ substitute (parseTerm term) substituteVariable (parseTerm substituteTerm)
29+
-- let substituteVariable = head var
30+
-- substituteTerm <- putStr "Input substitution term: " >> getLine
31+
-- putStrLn $ generateTerm $ substitute (parseTerm term) substituteVariable (parseTerm substituteTerm)

src/Substitution/Nameless.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ shift c d var@(NamelessVariable k)
66
| 0 <= k && k < c = var
77
| otherwise = NamelessVariable (k + d)
88
shift c d (NamelessApplication lhs rhs) = NamelessApplication (shift c d lhs) (shift c d rhs)
9-
shift c d (NamelessAbstraction depth body) = NamelessAbstraction depth (shift (c + 1) d body)
9+
shift c d (NamelessAbstraction body) = NamelessAbstraction $ shift (c + 1) d body
1010

1111
singleShift :: NamelessTerm -> NamelessTerm
1212
singleShift = shift 0 1
@@ -17,5 +17,5 @@ substituteNameless (NamelessVariable var) x term
1717
| otherwise = NamelessVariable var
1818
substituteNameless (NamelessApplication lhs rhs) x term =
1919
NamelessApplication (substituteNameless lhs x term) (substituteNameless rhs x term)
20-
substituteNameless (NamelessAbstraction depth body) x term =
21-
NamelessAbstraction depth (substituteNameless body (x + 1) (singleShift term))
20+
substituteNameless (NamelessAbstraction body) x term =
21+
NamelessAbstraction $ substituteNameless body (x + 1) (singleShift term)

src/Transformer.hs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,58 @@ module Transformer where
44

55
import Prelude hiding (lookup)
66
import Parser (Term (Variable, Application, Abstraction))
7-
import Data.Map (Map, member, lookup, insert, size)
7+
import Data.Map (Map, member, lookup, insert, size, foldrWithKey, findMin, keys, empty)
88
import Data.List (elemIndex, union)
9+
import Data.Char (chr, ord)
910

1011
data NamelessTerm
1112
= NamelessVariable Int
1213
| NamelessApplication NamelessTerm NamelessTerm
13-
| NamelessAbstraction Int NamelessTerm
14+
| NamelessAbstraction NamelessTerm
1415
deriving (Show)
1516

1617
type NamingContext = Map Char Int
17-
type BoundVariable = [Char]
18+
type BoundVariables = [Char]
1819

19-
toNameless :: Term -> Int -> BoundVariable -> NamingContext -> (NamelessTerm, NamingContext)
20-
toNameless (Variable var) depth bv context = case var `elemIndex` bv of
20+
toNamelessWithContext :: Term -> Int -> BoundVariables -> NamingContext -> (NamelessTerm, NamingContext)
21+
toNamelessWithContext (Variable var) depth bv context = case var `elemIndex` bv of
2122
Nothing -> case lookup var context of
2223
Nothing -> let index = size context
2324
in (NamelessVariable (index + depth), insert var index context)
2425
Just index -> (NamelessVariable (index + depth), context)
2526
Just index -> (NamelessVariable index, context)
2627

27-
toNameless (Application lhs rhs) depth bv context =
28-
let namelessLhs = toNameless lhs depth bv context
29-
namelessRhs = toNameless rhs depth bv (snd namelessLhs)
28+
toNamelessWithContext (Application lhs rhs) depth bv context =
29+
let namelessLhs = toNamelessWithContext lhs depth bv context
30+
namelessRhs = toNamelessWithContext rhs depth bv (snd namelessLhs)
3031
in (NamelessApplication (fst namelessLhs) (fst namelessRhs), snd namelessRhs)
3132

32-
toNameless (Abstraction argument body) depth bv context =
33-
let namelessBody = toNameless body (depth + 1) (insertBoundVariable argument bv) context
34-
in (NamelessAbstraction depth (fst namelessBody), snd namelessBody)
33+
toNamelessWithContext (Abstraction argument body) depth bv context =
34+
let namelessBody = toNamelessWithContext body (depth + 1) (insertBoundVariable argument bv) context
35+
in (NamelessAbstraction (fst namelessBody), snd namelessBody)
3536
where insertBoundVariable var bv = if var `elem` bv then bv else var:bv
3637

37-
-- a = Abstraction 'y' (Application (Variable 'x') (Application (Variable 'y') (Abstraction 'x' (Variable 'x'))))
38-
-- /x -> xy => Abstraction x (Application (Variable x) (Variable y))
39-
-- /01 => NamelessAbstraction 1 (NamelessApplication (Variable 0) (Variable 1))
40-
41-
-- /y -> xy/x -> x => /10/0
42-
-- (NamelessAbstraction (NamelessApplication (NamelessVariable 1) (NamelessApplication (NamelessVariable 0) (NamelessAbstraction (NamelessVariable 1))))
38+
toNameless :: Term -> (NamelessTerm, NamingContext)
39+
toNameless term = toNamelessWithContext term 0 [] empty
40+
41+
toNamedWithContext :: NamelessTerm -> BoundVariables -> NamingContext -> Term
42+
toNamedWithContext (NamelessVariable var) bv context
43+
| var >= length bv = Variable $ findKey (var - length bv) context
44+
| otherwise = Variable (bv !! var)
45+
toNamedWithContext (NamelessApplication lhs rhs) bv context =
46+
Application (toNamedWithContext lhs bv context) (toNamedWithContext rhs bv context)
47+
toNamedWithContext (NamelessAbstraction body) bv context = let updatedBoundVariables = extendBoundVariables bv
48+
in Abstraction (head updatedBoundVariables) (toNamedWithContext body updatedBoundVariables context)
49+
where extendBoundVariables :: BoundVariables -> BoundVariables
50+
extendBoundVariables [] = if 'a' `member` context then [nextVariable 'a' context] else "a"
51+
extendBoundVariables bv@(x:_) = nextVariable x context:bv
52+
53+
toNamed :: NamelessTerm -> NamingContext -> Term
54+
toNamed term = toNamedWithContext term []
55+
56+
findKey :: Eq v => v -> Map k v -> k
57+
findKey value map = foldrWithKey (\k v res -> if v == value then k else res) (fst $ findMin map) map
58+
59+
nextVariable :: Char -> NamingContext -> Char
60+
nextVariable var context = let next = chr $ ord var + 1
61+
in if next `member` context then nextVariable next context else next

0 commit comments

Comments
 (0)