packages feed

g2-0.1.0.1: quasiquote/DeBruijn/Interpreter.hs

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}

module DeBruijn.Interpreter ( Expr (..)
                            , Ident
                            , eval
                            , app
                            , lams
                            , num) where

import Data.Data
import G2.QuasiQuotes.G2Rep

type Ident = Int

data Expr = Var Ident
          | Lam Expr
          | App Expr Expr
          deriving (Show, Read, Eq, Data)

$(derivingG2Rep ''Expr)

type Stack = [Expr]

eval :: Expr -> Expr
eval = eval' []

eval' :: Stack -> Expr -> Expr
eval' (e:stck) (Lam e') = eval' stck (rep 1 e e')
eval' stck (App e1 e2) = eval' (e2:stck) e1
eval' stck e = app $ e:stck

rep :: Int -> Expr -> Expr -> Expr
rep i e v@(Var j)
    | i == j = e
    | otherwise = v
rep i e (Lam e') = Lam (rep (i + 1) e e')
rep i e (App e1 e2) = App (rep i e e1) (rep i e e2)

app :: [Expr] -> Expr
app = foldl1 App

lams :: Int -> Expr -> Expr
lams n e = iterate Lam e !! n

num :: Int -> Expr
num n = Lam $ Lam $ foldr1 App (replicate n (Var 2) ++ [Var 1])