diff options
Diffstat (limited to 'lambda-calcul/haskell/challenges.json')
| -rw-r--r-- | lambda-calcul/haskell/challenges.json | 252 |
1 files changed, 201 insertions, 51 deletions
diff --git a/lambda-calcul/haskell/challenges.json b/lambda-calcul/haskell/challenges.json index 75561c5..16d2f48 100644 --- a/lambda-calcul/haskell/challenges.json +++ b/lambda-calcul/haskell/challenges.json @@ -169,312 +169,462 @@ }, { "level": 28, + "description": "String literals are double-quoted values that self-evaluate \u2014 they need no reduction. What does \"hello\" reduce to?", + "expr": "\"hello\"", + "answer": "\"hello\"" + }, + { + "level": 29, + "description": "Strings can contain spaces and any printable character. What does \"foo bar\" reduce to?", + "expr": "\"foo bar\"", + "answer": "\"foo bar\"" + }, + { + "level": 30, + "description": "Apply the identity function to a string literal. What does ((lam (x) x) \"world\") reduce to?", + "expr": "((lam (x) x) \"world\")", + "answer": "\"world\"" + }, + { + "level": 31, + "description": "str-concat takes two strings and concatenates them. What does (str-concat \"foo\" \"bar\") reduce to?", + "expr": "(str-concat \"foo\" \"bar\")", + "answer": "\"foobar\"" + }, + { + "level": 32, + "description": "str-concat can be nested. What does (str-concat \"hello\" (str-concat \" \" \"world\")) reduce to?", + "expr": "(str-concat \"hello\" (str-concat \" \" \"world\"))", + "answer": "\"hello world\"" + }, + { + "level": 33, + "description": "str-length takes a string and returns its length as an integer. What does (str-length \"hello\") reduce to?", + "expr": "(str-length \"hello\")", + "answer": "5" + }, + { + "level": 34, + "description": "What does (str-length \"\") reduce to? The empty string has length zero.", + "expr": "(str-length \"\")", + "answer": "0" + }, + { + "level": 35, + "description": "str-slice takes a start index (inclusive), an end index (exclusive), and a string, and returns the sub-string. What does (str-slice 0 3 \"abcde\") reduce to?", + "expr": "(str-slice 0 3 \"abcde\")", + "answer": "\"abc\"" + }, + { + "level": 36, + "description": "What does (str-slice 1 4 \"abcde\") reduce to? Characters at indices 1, 2, and 3 are selected.", + "expr": "(str-slice 1 4 \"abcde\")", + "answer": "\"bcd\"" + }, + { + "level": 37, + "description": "str= takes two strings and returns the Church boolean True (lam (f t) t) if they are equal, False (lam (f t) f) otherwise. What does (str= \"abc\" \"abc\") reduce to?", + "expr": "(str= \"abc\" \"abc\")", + "answer": "(lam (f t) t)" + }, + { + "level": 38, + "description": "What does (str= \"abc\" \"xyz\") reduce to? The strings are not equal.", + "expr": "(str= \"abc\" \"xyz\")", + "answer": "(lam (f t) f)" + }, + { + "level": 39, + "description": "str< returns Church True when its first argument is lexicographically less than its second. What does (str< \"apple\" \"banana\") reduce to?", + "expr": "(str< \"apple\" \"banana\")", + "answer": "(lam (f t) t)" + }, + { + "level": 40, + "description": "What does (str< \"z\" \"a\") reduce to? \"z\" is not less than \"a\" lexicographically.", + "expr": "(str< \"z\" \"a\")", + "answer": "(lam (f t) f)" + }, + { + "level": 41, + "description": "Like arithmetic operators, string builtins support partial application. Applying str-concat to one argument produces a function waiting for its second. What does (str-concat \"hello\") reduce to?", + "expr": "(str-concat \"hello\")", + "answer": "(str-concat \"hello\")" + }, + { + "level": 42, + "description": "When a string builtin receives a free variable as an argument it cannot reduce and stays stuck. What does (str-concat x \"bar\") reduce to?", + "expr": "(str-concat x \"bar\")", + "answer": "(str-concat x \"bar\")" + }, + { + "level": 43, + "description": "Use def to bind a string, then apply str-length to it. What does (str-length greeting) produce in this program?", + "expr": "(def greeting \"hello\")\n(str-length greeting)", + "answer": "5" + }, + { + "level": 44, + "description": "Use let to bind a string and then concatenate it with another string. What does (let ((s \"hello\")) (str-concat s \"!\")) reduce to?", + "expr": "(let ((s \"hello\")) (str-concat s \"!\"))", + "answer": "\"hello!\"" + }, + { + "level": 45, + "description": "String builtins are first-class values and can be passed as arguments to lambdas. What does ((lam (f) (f \"hello\" \" world\")) str-concat) reduce to?", + "expr": "((lam (f) (f \"hello\" \" world\")) str-concat)", + "answer": "\"hello world\"" + }, + { + "level": 46, + "description": "A string literal can contain any character, including parentheses. The parser recognises ( and ) as delimiters only outside a string. What does \"(hello)\" reduce to?", + "expr": "\"(hello)\"", + "answer": "\"(hello)\"" + }, + { + "level": 47, + "description": "A string can contain only an opening parenthesis with no closing match \u2014 the parser does not need to see balanced parens inside a string. What does \"(\" reduce to?", + "expr": "\"(\"", + "answer": "\"(\"" + }, + { + "level": 48, + "description": "Likewise a string can start with a closing parenthesis. What does \")\" reduce to?", + "expr": "\")\"", + "answer": "\")\"" + }, + { + "level": 49, + "description": "A string that looks exactly like a lambda expression is still just a string \u2014 it is not evaluated. What does \"(lam (x) x)\" reduce to?", + "expr": "\"(lam (x) x)\"", + "answer": "\"(lam (x) x)\"" + }, + { + "level": 50, + "description": "Use str-concat to join two paren strings. The result is a correctly balanced parenthesis pair as a string value. What does (str-concat \"(\" \")\") reduce to?", + "expr": "(str-concat \"(\" \")\")", + "answer": "\"()\"" + }, + { + "level": 51, + "description": "str-length counts every character including parentheses. What does (str-length \"(hello)\") reduce to?", + "expr": "(str-length \"(hello)\")", + "answer": "7" + }, + { + "level": 52, + "description": "str-slice works on strings containing parentheses just like any other string. What does (str-slice 0 3 \"(ab)\") reduce to?", + "expr": "(str-slice 0 3 \"(ab)\")", + "answer": "\"(ab\"" + }, + { + "level": 53, "description": "The interpreter now has built-in arithmetic operators. + takes two integers and returns their sum. What does (+ 3 4) reduce to?", "expr": "(+ 3 4)", "answer": "7" }, { - "level": 29, + "level": 54, "description": "The built-in - subtracts its second argument from its first. What does (- 10 3) reduce to?", "expr": "(- 10 3)", "answer": "7" }, { - "level": 30, + "level": 55, "description": "The built-in * multiplies two integers. What does (* 6 7) reduce to?", "expr": "(* 6 7)", "answer": "42" }, { - "level": 31, + "level": 56, "description": "div performs integer division (truncated toward negative infinity). What does (div 17 5) reduce to?", "expr": "(div 17 5)", "answer": "3" }, { - "level": 32, + "level": 57, "description": "mod returns the remainder of integer division. What does (mod 17 5) reduce to?", "expr": "(mod 17 5)", "answer": "2" }, { - "level": 33, + "level": 58, "description": "neg is a unary built-in that negates its argument. What does (neg 5) reduce to?", "expr": "(neg 5)", "answer": "-5" }, { - "level": 34, + "level": 59, "description": "Built-ins compose freely. * and + can be nested just like lambda applications. What does (* 2 (+ 3 4)) reduce to?", "expr": "(* 2 (+ 3 4))", "answer": "14" }, { - "level": 35, + "level": 60, "description": "Pythagorean-style expression: (+ (* 3 3) (* 4 4)) computes 9 + 16. What is the result?", "expr": "(+ (* 3 3) (* 4 4))", "answer": "25" }, { - "level": 36, + "level": 61, "description": "= is a built-in equality test. It returns the Church boolean True (lam (f t) t) when both arguments are equal and False (lam (f t) f) otherwise. What does (= 42 42) reduce to?", "expr": "(= 42 42)", "answer": "(lam (f t) t)" }, { - "level": 37, + "level": 62, "description": "What does (= 42 0) reduce to? The two integers are not equal, so = returns the Church boolean False.", "expr": "(= 42 0)", "answer": "(lam (f t) f)" }, { - "level": 38, + "level": 63, "description": "< is a built-in less-than test. It returns the Church boolean True when the first argument is strictly less than the second, False otherwise. What does (< 3 5) reduce to?", "expr": "(< 3 5)", "answer": "(lam (f t) t)" }, { - "level": 39, + "level": 64, "description": "What does (< 5 3) reduce to? 5 is not less than 3, so < returns the Church boolean False.", "expr": "(< 5 3)", "answer": "(lam (f t) f)" }, { - "level": 40, + "level": 65, "description": "Built-ins support partial application just like lambdas. Applying + to only one argument produces a function waiting for its second argument. What does (+ 1) reduce to?", "expr": "(+ 1)", "answer": "(+ 1)" }, { - "level": 41, + "level": 66, "description": "A partially applied built-in is a first-class value that can be passed to and invoked by a lambda. What does ((lam (f) (f 10)) (+ 5)) reduce to?", "expr": "((lam (f) (f 10)) (+ 5))", "answer": "15" }, { - "level": 42, + "level": 67, "description": "When a built-in operator receives a free variable as one of its arguments it cannot reduce and stays as a stuck neutral term. What does (+ x 1) reduce to?", "expr": "(+ x 1)", "answer": "(+ x 1)" }, { - "level": 43, + "level": 68, "description": "Division by zero cannot be reduced \u2014 it stays as a stuck neutral application. What does (div 7 0) reduce to?", "expr": "(div 7 0)", "answer": "(div 7 0)" }, { - "level": 44, + "level": 69, "description": "Use def to bind a lambda that uses * to square its argument, then apply it. What does (square 9) produce in this program?", "expr": "(def square (lam (x) (* x x)))\n(square 9)", "answer": "81" }, { - "level": 45, + "level": 70, "description": "Use let to bind two integers and compute the sum of their squares. What does (let ((x 3) (y 4)) (+ (* x x) (* y y))) reduce to?", "expr": "(let ((x 3) (y 4)) (+ (* x x) (* y y)))", "answer": "25" }, { - "level": 46, + "level": 71, "description": "Built-in operators are first-class values: they can be passed as arguments to lambdas. Here a lambda takes an operator f and two arguments x y and applies (f x y). What does ((lam (f x y) (f x y)) + 10 20) reduce to?", "expr": "((lam (f x y) (f x y)) + 10 20)", "answer": "30" }, { - "level": 47, + "level": 72, "description": "Introduce And. And a b = a False b: if a is True it selects its second argument (b); if a is False it selects its first argument (False). Evaluate (And True True).", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def Or (lam (a b) (a b True)))\n(def And (lam (a b) (a False b)))\n(And True True)", "answer": "(lam (f t) t)" }, { - "level": 48, + "level": 73, "description": "Combine Or, And and Not. Evaluate (And (Or False True) (Not False)). Both sub-expressions must reduce to True for And to return True.", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def Not (lam (b) (b True False)))\n(def Or (lam (a b) (a b True)))\n(def And (lam (a b) (a False b)))\n(And (Or False True) (Not False))", "answer": "(lam (f t) t)" }, { - "level": 49, + "level": 74, "description": "Xor (exclusive or) is True when exactly one argument is True. It can be defined as And (Or a b) (Not (And a b)). Evaluate (Xor True False).", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def Not (lam (b) (b True False)))\n(def And (lam (a b) (a False b)))\n(def Or (lam (a b) (a b True)))\n(def Xor (lam (a b) (And (Or a b) (Not (And a b)))))\n(Xor True False)", "answer": "(lam (f t) t)" }, { - "level": 50, + "level": 75, "description": "Evaluate (Xor False False). Two identical inputs to Xor should always yield False.", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def Not (lam (b) (b True False)))\n(def And (lam (a b) (a False b)))\n(def Or (lam (a b) (a b True)))\n(def Xor (lam (a b) (And (Or a b) (Not (And a b)))))\n(Xor False False)", "answer": "(lam (f t) f)" }, { - "level": 51, + "level": 76, "description": "Church-encoded if-then-else. Because our True selects its second argument and False selects its first, ite must swap the branches: ite c t e = c e t. Evaluate (ite True a b) \u2014 which branch is returned?", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def Not (lam (b) (b True False)))\n(def And (lam (a b) (a False b)))\n(def Or (lam (a b) (a b True)))\n(def ite (lam (c t e) (c e t)))\n(ite True a b)", "answer": "a" }, { - "level": 52, + "level": 77, "description": "Evaluate (ite False a b). When the condition is False, the else-branch should be returned.", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def Not (lam (b) (b True False)))\n(def And (lam (a b) (a False b)))\n(def Or (lam (a b) (a b True)))\n(def ite (lam (c t e) (c e t)))\n(ite False a b)", "answer": "b" }, { - "level": 53, + "level": 78, "description": "Church-encoded pairs. pair x y = lam f -> f x y stores two values by passing them to a selector function. fst p = p (lam x y -> x) retrieves the first. Evaluate (fst (pair a b)).", "expr": "(def pair (lam (x y f) (f x y)))\n(def fst (lam (p) (p (lam (x y) x))))\n(def snd (lam (p) (p (lam (x y) y))))\n(fst (pair a b))", "answer": "a" }, { - "level": 54, + "level": 79, "description": "snd p = p (lam x y -> y) retrieves the second element of a Church pair. Evaluate (snd (pair a b)).", "expr": "(def pair (lam (x y f) (f x y)))\n(def fst (lam (p) (p (lam (x y) x))))\n(def snd (lam (p) (p (lam (x y) y))))\n(snd (pair a b))", "answer": "b" }, { - "level": 55, + "level": 80, "description": "Pairs can be nested. (pair a (pair b c)) is a pair whose second element is itself a pair. Evaluate (snd (snd (pair a (pair b c)))).", "expr": "(def pair (lam (x y f) (f x y)))\n(def fst (lam (p) (p (lam (x y) x))))\n(def snd (lam (p) (p (lam (x y) y))))\n(snd (snd (pair a (pair b c))))", "answer": "c" }, { - "level": 56, + "level": 81, "description": "swap exchanges the two elements of a pair: swap p = pair (snd p) (fst p). Evaluate (fst (swap (pair a b))). After swapping, fst should return what was previously snd.", "expr": "(def pair (lam (x y f) (f x y)))\n(def fst (lam (p) (p (lam (x y) x))))\n(def snd (lam (p) (p (lam (x y) y))))\n(def swap (lam (p) (pair (snd p) (fst p))))\n(fst (swap (pair a b)))", "answer": "b" }, { - "level": 57, + "level": 82, "description": "Church numerals encode natural numbers as higher-order functions: n applies its first argument (the successor step) to its second argument (the base) exactly n times. zero = lam s z -> z applies s zero times. Evaluate (zero f x).", "expr": "(def zero (lam (s z) z))\n(zero f x)", "answer": "x" }, { - "level": 58, + "level": 83, "description": "two = lam s z -> s (s z) applies s twice. Evaluate (two f x) \u2014 you should see f applied to x twice.", "expr": "(def two (lam (s z) (s (s z))))\n(two f x)", "answer": "(f (f x))" }, { - "level": 59, + "level": 84, "description": "three = lam s z -> s (s (s z)) applies s three times. Evaluate (three f x).", "expr": "(def three (lam (s z) (s (s (s z)))))\n(three f x)", "answer": "(f (f (f x)))" }, { - "level": 60, + "level": 85, "description": "isZero tests whether a Church numeral is zero. isZero n = n (lam x -> False) True: if n > 0 the step function (lam x -> False) is applied at least once, discarding its argument and returning False; if n = 0 the base True is returned. Evaluate (isZero zero).", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def zero (lam (s z) z))\n(def isZero (lam (n) (n (lam (x) False) True)))\n(isZero zero)", "answer": "(lam (f t) t)" }, { - "level": 61, + "level": 86, "description": "Evaluate (isZero three). Three is not zero, so the step function fires and the result is False.", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def three (lam (s z) (s (s (s z)))))\n(def isZero (lam (n) (n (lam (x) False) True)))\n(isZero three)", "answer": "(lam (f t) f)" }, { - "level": 62, + "level": 87, "description": "The I combinator (identity): I x = x. It is the simplest combinator and the building block of the SKI calculus. Evaluate (I a).", "expr": "(def I (lam (x) x))\n(I a)", "answer": "a" }, { - "level": 63, + "level": 88, "description": "The K combinator (constant): K x y = x. It ignores its second argument and always returns its first. Evaluate (K a b).", "expr": "(def K (lam (x y) x))\n(K a b)", "answer": "a" }, { - "level": 64, + "level": 89, "description": "The S combinator (substitution): S f g x = f x (g x). It distributes its third argument over two functions and applies the results. Evaluate (S f g x) \u2014 f and g are free variables here.", "expr": "(def S (lam (f g x) ((f x) (g x))))\n(S f g x)", "answer": "(f x (g x))" }, { - "level": 65, + "level": 90, "description": "SKI completeness: S K K encodes the identity function. S K K x = K x (K x) = x. Evaluate (S K K a) and confirm it equals a.", "expr": "(def S (lam (f g x) ((f x) (g x))))\n(def K (lam (x y) x))\n(S K K a)", "answer": "a" }, { - "level": 66, + "level": 91, "description": "The B combinator (composition): B f g x = f (g x). It is function composition. Evaluate (B f g x) \u2014 you should see f applied to the result of g applied to x.", "expr": "(def B (lam (f g x) (f (g x))))\n(B f g x)", "answer": "(f (g x))" }, { - "level": 67, + "level": 92, "description": "The C combinator (flip): C f x y = f y x. It flips the order of the last two arguments of a function. Evaluate (C f a b).", "expr": "(def C (lam (f x y) (f y x)))\n(C f a b)", "answer": "(f b a)" }, { - "level": 68, + "level": 93, "description": "The W combinator (duplication): W f x = f x x. It applies f to x twice, duplicating the argument. Evaluate (W f a).", "expr": "(def W (lam (f x) (f x x)))\n(W f a)", "answer": "(f a a)" }, { - "level": 69, + "level": 94, "description": "Scott-encoded lists. nil = lam c n -> n (the empty list). cons h t = lam c n -> c h t stores head and tail directly. head l = l (lam h t -> h) nil extracts the first element. Evaluate (head (cons a nil)).", "expr": "(def nil (lam (c n) n))\n(def cons (lam (h t c n) (c h t)))\n(def head (lam (l) (l (lam (h t) h) nil)))\n(head (cons a nil))", "answer": "a" }, { - "level": 70, + "level": 95, "description": "tail l = l (lam h t -> t) nil retrieves the rest of a Scott-encoded list. Evaluate (head (tail (cons a (cons b nil)))) \u2014 the head of the tail of a two-element list is its second element.", "expr": "(def nil (lam (c n) n))\n(def cons (lam (h t c n) (c h t)))\n(def head (lam (l) (l (lam (h t) h) nil)))\n(def tail (lam (l) (l (lam (h t) t) nil)))\n(head (tail (cons a (cons b nil))))", "answer": "b" }, { - "level": 71, + "level": 96, "description": "isNil tests whether a Scott-encoded list is empty. isNil l = l (lam h t -> False) True: a non-empty list immediately calls its cons branch returning False; nil returns its base True. Evaluate (isNil nil).", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def nil (lam (c n) n))\n(def cons (lam (h t c n) (c h t)))\n(def isNil (lam (l) (l (lam (h t) False) True)))\n(isNil nil)", "answer": "(lam (f t) t)" }, { - "level": 72, + "level": 97, "description": "Evaluate (isNil (cons a nil)). A non-empty list is not nil, so the result should be False.", "expr": "(def False (lam (f t) f))\n(def True (lam (f t) t))\n(def nil (lam (c n) n))\n(def cons (lam (h t c n) (c h t)))\n(def isNil (lam (l) (l (lam (h t) False) True)))\n(isNil (cons a nil))", "answer": "(lam (f t) f)" }, { - "level": 73, + "level": 98, "description": "Church-encoded sum types (Either). Left x = lam l r -> l x tags a value as Left; Right x = lam l r -> r x tags it as Right. either f g e = e f g eliminates the sum by applying the matching handler. Evaluate (either f g (Left a)).", "expr": "(def Left (lam (x l r) (l x)))\n(def Right (lam (x l r) (r x)))\n(def either (lam (f g e) (e f g)))\n(either f g (Left a))", "answer": "(f a)" }, { - "level": 74, + "level": 99, "description": "Evaluate (either f g (Right a)). The Right handler g should be applied to a.", "expr": "(def Left (lam (x l r) (l x)))\n(def Right (lam (x l r) (r x)))\n(def either (lam (f g e) (e f g)))\n(either f g (Right a))", "answer": "(g a)" }, { - "level": 75, + "level": 100, "description": "Church-encoded option (Maybe). None = lam n s -> n is the absent case. Some x = lam n s -> s x wraps a value. fromOption default opt = opt default (lam x -> x) returns the wrapped value or the default. Evaluate (fromOption a None).", "expr": "(def None (lam (n s) n))\n(def Some (lam (x n s) (s x)))\n(def fromOption (lam (default opt) (opt default (lam (x) x))))\n(fromOption a None)", "answer": "a" }, { - "level": 76, + "level": 101, "description": "Evaluate (fromOption a (Some b)). The option contains b, so the default a is ignored and b is returned.", "expr": "(def None (lam (n s) n))\n(def Some (lam (x n s) (s x)))\n(def fromOption (lam (default opt) (opt default (lam (x) x))))\n(fromOption a (Some b))", "answer": "b" }, { - "level": 77, + "level": 102, "description": "mapOption applies a function inside an Option without unwrapping it. mapOption f opt = opt None (lam x -> Some (f x)): None maps to None; Some x maps to Some (f x). Evaluate (mapOption f (Some a)) and give its fully reduced form.", "expr": "(def None (lam (n s) n))\n(def Some (lam (x n s) (s x)))\n(def mapOption (lam (f opt) (opt None (lam (x) (Some (f x))))))\n(mapOption f (Some a))", "answer": "(lam (n s) (s (f a)))" }, { - "level": 78, + "level": 103, "description": "The Kleene predecessor uses a pair-stepping trick to compute pred n = n - 1 (with pred zero = zero). Starting from (pair zero zero), each step shifts: (pair (snd p)) (succ (snd p)). After n steps fst of the pair is n-1. Evaluate (pred zero) \u2014 it should return zero.", "expr": "(def zero (lam (s z) z))\n(def one (lam (s z) (s z)))\n(def pair (lam (x y f) (f x y)))\n(def fst (lam (p) (p (lam (x y) x))))\n(def snd (lam (p) (p (lam (x y) y))))\n(def succ (lam (n s z) (s ((n s) z))))\n(def pred (lam (n) (fst (n (lam (p) (pair (snd p) (succ (snd p)))) (pair zero zero)))))\n(pred zero)", "answer": "(lam (s z) z)" }, { - "level": 79, + "level": 104, "description": "Evaluate (pred one) using the same Kleene predecessor. After one pair-step starting from (pair zero zero) the fst is still zero. Confirm that the predecessor of one is zero.", "expr": "(def zero (lam (s z) z))\n(def one (lam (s z) (s z)))\n(def pair (lam (x y f) (f x y)))\n(def fst (lam (p) (p (lam (x y) x))))\n(def snd (lam (p) (p (lam (x y) y))))\n(def succ (lam (n s z) (s ((n s) z))))\n(def pred (lam (n) (fst (n (lam (p) (pair (snd p) (succ (snd p)))) (pair zero zero)))))\n(pred one)", "answer": "(lam (s z) z)" |
