Advertisement
Guest User

Untitled

a guest
Oct 16th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.33 KB | None | 0 0
  1. -- ***************************************************
  2.  
  3. -- 6.820 - Program Analysis - Fall 2019
  4. -- PROBLEM SET 1
  5.  
  6. -- ***************************************************
  7.  
  8.  
  9. -- ---------------------------------------------------
  10. -- Problem 1
  11. -- ---------------------------------------------------
  12.  
  13. -- Just copying some code from the problem set into this file
  14. -- to check that we can load it into ghci and work with it.
  15.  
  16. apply_n f n x =
  17. if n == 0 then x
  18. else apply_n f (n - 1) (f x)
  19.  
  20. plus a b = apply_n ((+) 1) b a
  21. mult a b = apply_n ((+) a) b 0
  22. expon a b = apply_n ((*) a) b 1
  23.  
  24.  
  25. -- ---------------------------------------------------
  26. -- Problem 2
  27. -- ---------------------------------------------------
  28.  
  29. -- Don't know calculus, so...
  30.  
  31.  
  32. -- ---------------------------------------------------
  33. -- Problem 3 : Sets
  34. -- ---------------------------------------------------
  35.  
  36. type IntSet = (Int -> Bool)
  37.  
  38. isMember :: IntSet -> Int -> Bool
  39. isMember f x = f x
  40.  
  41.  
  42. -- Part a : Simple Sets
  43. -- ---------------------------------------------------
  44.  
  45. -- A "set" is a function from Int to Bool.
  46. -- It checks if an integer is a member of the set.
  47. -- An empty set has no members, so no matter what Int
  48. -- you give it, it should return False.
  49. emptySet :: IntSet -- IntSet == Int -> Bool
  50. emptySet x = False
  51.  
  52. -- Check it:
  53. -- isMember emptySet 3 == False
  54. -- isMember emptySet 5 == False
  55.  
  56. -- The "allInts" set contains all integers.
  57. -- So no matter which integer you give it, it should
  58. -- return True.
  59. allInts :: IntSet
  60. allInts x = True
  61.  
  62. -- Check it:
  63. -- isMember allInts 3 == True
  64. -- isMember allInts 10 == True
  65.  
  66.  
  67. -- Part b : Intervals
  68. -- ---------------------------------------------------
  69.  
  70. -- interval x y contains all the integers in [x, y].
  71. interval :: Int -> Int -> IntSet -- Int -> Int -> (Int -> Bool)
  72. interval lBound uBound = \x -> lBound <= x && x <= uBound
  73.  
  74. -- Check it:
  75. -- let range = interval 5 10
  76. -- range' = interval 3 7
  77. -- in isMember range 7 == True
  78. -- isMember range 13 == False
  79. -- isMember range' 2 == False
  80. -- isMember range' 5 == False
  81.  
  82.  
  83. -- Part c : Primes
  84. -- ---------------------------------------------------
  85.  
  86. -- Don't care right now...
  87.  
  88.  
  89. -- Part d : Set Operators
  90. -- ---------------------------------------------------
  91.  
  92. -- Boolean Operators
  93.  
  94. -- A "set" is a function that takes an Int and returns a Bool
  95. -- indicating whether the Int is in the Set.
  96. -- So to build the intersection of two "sets" f and g,
  97. -- we build a function that takes an Int, and checks if
  98. -- that Int is in both sets f and g.
  99. setIntersection :: IntSet -> IntSet -> IntSet
  100. setIntersection f g = \x -> f x && g x
  101.  
  102. -- Or in either sets f or g.
  103. setUnion:: IntSet -> IntSet -> IntSet
  104. setUnion f g = \x -> f x || g x
  105.  
  106. -- Or not in set f.
  107. setComplement :: IntSet -> IntSet
  108. setComplement f = \x -> not (f x)
  109.  
  110. -- Check it
  111. -- let range = interval 5 10
  112. -- range' = interval 3 7
  113. -- intersection range range'
  114. -- union range range'
  115. -- complement range
  116. -- in isMember intersection 6 == True
  117. -- isMember intersection 4 == False
  118. -- isMember union 6 == True
  119. -- isMember union 4 == True
  120. -- isMember complement 3 == False
  121.  
  122.  
  123. -- Part e : Equality
  124. -- ---------------------------------------------------
  125.  
  126. -- Not sure. Maybe do set equality for a range, and check every Int in the range.
  127.  
  128.  
  129. -- ---------------------------------------------------
  130. -- Problem 4 : Using Lambda Combinators
  131. -- ---------------------------------------------------
  132.  
  133. type LamVar = Char
  134. type LamBool = LamVar -> LamVar -> LamVar
  135.  
  136. -- True is represented as a function that takes two arguments and returns the first.
  137. true :: LamBool
  138. true = \x -> \y -> x
  139.  
  140. -- False is represented as a function that takes two arguments and returns the second.
  141. false :: LamBool
  142. false = \x -> \y -> y
  143.  
  144. -- Cond is represented as a function that takes a condition and two other arguments.
  145. -- If the condition is true, it returns the first argument, otherwise the second.
  146. -- cond :: LamBool -> LamBool -> LamBool -> LamBool
  147. -- cond = \c -> \e1 -> \e2 -> c e1 e2
  148.  
  149. -- Check it:
  150. -- true 'x' 'y' == 'x'
  151. -- false 'x' 'y' == 'y'
  152. -- cond true 'x' 'y' == 'x'
  153. -- cond false 'x' 'y' == 'y'
  154.  
  155. -- and :: (Char -> Char -> Char) -> (Char -> Char -> Char) -> (Char -> Char -> Char)
  156. -- and = \e1 -> \e2 -> cond e1 e2 false
  157.  
  158. -- bnot = \b1 -> cond b1 false true
  159.  
  160.  
  161.  
  162.  
  163.  
  164. -- ---------------------------------------------------
  165. -- Problem 6 : A Normal Order NF Interpreter
  166. -- ---------------------------------------------------
  167.  
  168.  
  169. -- Part c: Renaming Function in Haskell
  170. -- ---------------------------------------------------
  171.  
  172. -- Expressions can have the form of variables, applications, or abstractions.
  173. data Expr =
  174. Var Name -- a variable
  175. | App Expr Expr -- application
  176. | Lambda Name Expr -- lambda abstraction
  177. deriving
  178. (Eq, Show) -- use default compiler generated Eq and Show instances
  179.  
  180. -- A variable can have a string name.
  181. type Name = String -- a variable name
  182.  
  183. -- @replaceVar ("x", y) z@ takes the expression @z@, and it replaces
  184. -- all free occurrences of "x" with the expression @y@.
  185. replaceVar :: (Name, Expr) -> Expr -> Expr
  186. replaceVar (n, e) src =
  187. case src of
  188. -- Is the expression a variable?
  189. -- If so, replace the variable if it's the one we're looking to replace.
  190. Var n' ->
  191. case n == n' of
  192. True -> e -- If it matches @n@, replace it with @e@.
  193. False -> src -- Otherwise, there's no match to replace.
  194.  
  195. -- Is the expression an application?
  196. -- If so, replace the variables in each of the subexpressions.
  197. App e1 e2 -> App (replaceVar (n, e) e1) (replaceVar (n, e) e2)
  198.  
  199. -- Is the expression a lambda?
  200. Lambda n' e' ->
  201. case n == n' of
  202. True -> src -- @n@ is bound (not free) so we can't replace it.
  203. False -> Lambda n' (replaceVar (n, e) e') -- Replace @n@ in the body.
  204. -- Note that this last replacement is naive.
  205. -- It doesn't prevent variable capture.
  206.  
  207.  
  208. -- Check it:
  209. -- let x = Var "x"
  210. -- let y = Var "y"
  211. -- replaceVar ("x", y) x -- Returns: @Var "y"@ (it replaces "x" with y)
  212. -- replaceVar ("y", y) x -- Returns @Var "x"< (there is no free "x", so it replaces nothing)
  213. -- let a = App x y
  214. -- let b = App y y
  215. -- replaceVar ("x", y) a -- Returns @App (Var "y") (Var "y") (it replaces the first "x" with "y")
  216. -- replaceVar ("x", y) b -- Returns @App (Var "y") (Var "y") (no "x" in either expression)
  217. -- let z = Var "z"
  218. -- let c = Lambda "x" z
  219. -- let d = Lambda "y" z
  220. -- replaceVar ("x", y) c -- Returns the expression unchanged, because "x" is bound.
  221. -- replaceVar ("z", y) d -- Returns the body changed to "y". But now "y" is captured!
  222.  
  223.  
  224. -- Part d: Doing a Single Step
  225. -- ---------------------------------------------------
  226.  
  227. -- Do one step of reduction.
  228. normNF_OneStep :: ([Name], Expr) -> Maybe ([Name], Expr)
  229. normNF_OneStep (name:names, e) =
  230. case e of
  231.  
  232. -- A var can't be reduced any further.
  233. Var _ -> Nothing
  234.  
  235. -- If it's an abstraction, we can't reduce further.
  236. Lambda _ _ -> Nothing
  237.  
  238. -- If there's an application, we might have a redex.
  239. App e1 e2 ->
  240. case e1 of
  241.  
  242. -- If the first term is a var, we can't reduce further.
  243. Var _ -> Nothing
  244.  
  245. -- If the first term is an application, we can't reduce further.
  246. App _ _ -> Nothing
  247.  
  248. -- If the first term is an abstraction, we can apply it to the argument.
  249. Lambda n' e' ->
  250. -- Alpha rename the bound variables in the body, then do the reduction.
  251. let alpha_converted_e = replaceVar (n', Var name) e'
  252. reduced_e = replaceVar (name, e2) alpha_converted_e
  253. in Just (names, reduced_e)
  254.  
  255. -- Check it:
  256. -- let x = Var "x"
  257. -- let y = Var "y"
  258. -- let z = Var "z"
  259. -- let lxx = Lambda "x" x
  260. -- let lxy = Lambda "x" y
  261. -- let lxx_y = App lxx y
  262. -- normNF_OneStep (["a", "b"], lxx) ==> Returns: Nothing
  263. -- normNF_OneStep (["a", "b"], lxx_y) ==> Returns: Just (["b"],Var "y")
  264.  
  265.  
  266. -- Part e: Repitition
  267. -- ---------------------------------------------------
  268.  
  269. -- Do @n@ steps of reduction.
  270. normNF_n :: Int -> ([Name], Expr) -> ([Name], Expr)
  271. normNF_n gas (names, e) =
  272. case gas of
  273. 0 -> (names, e)
  274. _ ->
  275. case normNF_OneStep (names, e) of
  276. Nothing -> (names, e)
  277. Just (names', e') -> normNF_n (gas - 1) (names', e')
  278.  
  279. -- Check it:
  280. -- let x = Var "x"
  281. -- let y = Var "y"
  282. -- let z = Var "z"
  283. -- let lxx = Lambda "x" x
  284. -- let lxx_y = App lxx y
  285. -- normNF_n 3 (["a", "b"], lxx_y) ==> Returns: (["b"],Var "y")
  286. -- let lylxx_y_z = App (Lambda "y" (App lxx y)) z
  287. -- normNF_n 3 (["a", "b", "c"], lylxx_y_z) ==> Returns: (["c"],Var "z")
  288.  
  289.  
  290. -- Part f: Generating New Names
  291. -- ---------------------------------------------------
  292.  
  293. -- A list of integers.
  294. freshNames = [1..]
  295.  
  296. -- Gather all names used in an expression.
  297. usedNames :: Expr -> [Name]
  298. usedNames e =
  299. case e of
  300. Var n -> [n]
  301. App e1 e2 -> (usedNames e1) ++ (usedNames e2)
  302. Lambda n e' -> (n : usedNames e')
  303.  
  304. -- Check it:
  305. -- let x = Var "x"
  306. -- let y = Var "y"
  307. -- let lxx = Lambda "x" x
  308. -- let lxx_y = App lxx y
  309. -- usedNames lxx_y ==> Returns: ["x", "x", "y"]
  310.  
  311.  
  312. -- Part g: Finishing Up
  313. -- ---------------------------------------------------
  314.  
  315. -- @normNF 3 (App (Lambda "x" (Var "x")) (Var "y"))@ performs 3 reductions.
  316. normNF :: Int -> Expr -> Expr
  317. normNF gas e =
  318. let taken_names = usedNames e
  319. num_names = length taken_names
  320. fresh_names = map show (take num_names freshNames)
  321. (fresh_names', e') = normNF_n gas (fresh_names, e)
  322. in e'
  323.  
  324. -- Check it:
  325. -- let x = Var "x"
  326. -- let y = Var "y"
  327. -- let lxx = Lambda "x" x
  328. -- let lxx_y = App lxx y
  329. -- normNF 5 lxx_y ==> Returns: Var "y"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement