4

I am trying to solve sure but can you SKI on codewars. It is about to express lambda in SKI combinators. Source is at https://repl.it/@delta4d/SKI.

After some researching, especially the Combinatory Logic, I am able to solve all the cases except xor.

I first translates xor into

xor x y = if y 
          then if x
               then false
               else true
          else x

which is

xor = \x y -> y (x false true) x
-- false = K I
-- true = K

applying lambda to SKI rules, I got

\x.\y.y (x false true) x
\x.S (\y.y (x false true)) (K x)
\x.S (S I (K (x false true))) (K x)
S (\x.S (S I (K (x false true)))) K
S (S (K S) (\x.S I (K (x false true)))) K
S (S (K S) (S (K (S I)) (\x.K (x false true)))) K
S (S (K S) (S (K (S I)) (S (K K) (\x.x false true)))) K
S (S (K S) (S (K (S I)) (S (K K) (S (\x.x false) (K true))))) K
S (S (K S) (S (K (S I)) (S (K K) (S (S I (K false)) (K true))))) K

I have checked the SKI presentation on http://ski.aditsu.net, it works fine.

Haskell sources compiles, but got runtime error.

Codewars reports:

Couldn't match type `a' with `Bool' a'
  `a' is a rigid type variable bound by
      a type expected by the context: a -> a -> a at Kata.hs:66:9
Expected type: SKI
                 (Bool' a -> (Bool' a -> Bool' a -> Bool' a) -> a -> a -> a)
  Actual type: SKI (Bool' (Bool' a))
In the second argument of `xorF', namely `true'
In the second argument of `($)', namely `xorF true true'

I have test on local with prettyPrintSKI $ Ap (Ap xor' false) true, and it reports:

• Occurs check: cannot construct the infinite type: a20 ~ Bool' a20
  Expected type: SKI
                   (Bool' a20 -> (Bool' a20 -> Bool' a20 -> Bool' a20) -> Bool' a20)
    Actual type: SKI (Bool' (Bool' a20))
• In the second argument of ‘Ap’, namely ‘true’
  In the second argument of ‘($)’, namely ‘Ap (Ap xor' false) true’
  In the expression: prettyPrintSKI $ Ap (Ap xor' false) true

What is the infinite type about? what is the rigid type?

I am doing the same thing on or as or = \x y -> x true y, and it works just fine.


  1. https://www.codewars.com/kata/sure-but-can-you-ski-i
  2. https://en.wikipedia.org/wiki/Combinatory_logic
  3. http://ski.aditsu.net
dfeuer
  • 44,398
  • 3
  • 56
  • 155
delta
  • 3,643
  • 13
  • 21
  • 1
    In Haskell `True` and `False` are constructors, hence you should use an uppercase, or in case you want the lambda variant, then you can not use an `if`, but then you should call the functions. – Willem Van Onsem Apr 30 '18 at 07:39
  • Can you share your exact implementation? – Willem Van Onsem Apr 30 '18 at 07:40
  • 1
    @WillemVanOnsem, here `true` and `false` is not the same in Haskell. It defines as `false = Ap K I`, `true = K`. My intention of using `if then else` has nothing to do with Haskell, just pseudo code. You can see the problem on codewars for more info. – delta Apr 30 '18 at 07:42
  • @WillemVanOnsem https://repl.it/@delta4d/SKI – delta Apr 30 '18 at 07:46

1 Answers1

2

The problem comes from the double use of x in λxy.y (x false true) x. It's forced to have two types simultaneously. Since y uses x, y must return something of let's say type a. Now this means that x false true is also of type a. So something of type a must be (b -> b -> a) (for some b). But that's impossible, since that means a must contain itself.

It's worth noting that your solution is correct wrt. SK, just not Haskell's type system. So to fix we need to not use x twice with different types. So why not make them the same type with λxy.y(x false true)(x true false)?

Probie
  • 1,341
  • 7
  • 15
  • 2
    I guess that if `x` has a polymorphic type `forall a. a->a->a` then that code could be compiled. This requires higher rank types, and turning on the suitable Haskell extensions. – chi Apr 30 '18 at 13:06