Advertisement
NLinker

Y combinator

Jun 9th, 2017
393
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. In class, someone pointed out that the standard definition of fix I
  2. gave was kind of unsatisfying:
  3.  
  4.     fix f = let x = f x in x
  5.  
  6. because it uses recursion.  So if the point is to implement recursion
  7. without recursion, then since fix uses recursion, I didn't really
  8. achieve the goal.  Really the point was to set up for mfix, but still
  9. this was a valid point.
  10.  
  11. The next question raised was whether you could something like the Y
  12. combinator in Haskell.  The Y combinator is a fixed point combinator
  13. for the untyped lambda calculus, which can be described by the
  14. following pseudo-Haskell code:
  15.  
  16.    y f = (\x -> f (x x)) (\x -> f (x x))
  17.  
  18. Now, why is this pseudo-Haskell?  The problem is that Haskell is more
  19. like a *typed* lambda calculus.  And so somehow we would need to have
  20. type for x, which is being applied to itself.  In fact, it is not
  21. possible to apply a function to itself in Haskell, because there is no
  22. valid type for x.
  23.  
  24. As it happens, in order to apply a function to itself in the typed
  25. lambda calculus, you need recursive types.  There are basically two
  26. kinds of recursive types.  True, transparently recursive types are
  27. called equi-recursive types.  Haskell doesn't support equi-recursive
  28. types, but if it did, you could define a recursive type alias as
  29. follows:
  30.  
  31.     type SelfApply t = (SelfApply t) -> t
  32.  
  33. Then if the type of x were SelfApply t, the type of x x would be t,
  34. and you could use this to build a Y combinator.  But we can't since
  35. Haskell won't allow the above SelfApply.
  36.  
  37. What Haskell does support is so-called iso-recursive types.  These are
  38. recursive types, but in which there is a constructor, so that to
  39. expose the recursive instance of the type, you must unpack the
  40. constructor.  Happily, iso-recursive types are good enough to
  41. implement self-application and the Y combinator, it's just a bit more
  42. cumbersome.
  43.  
  44. So here you go, the Y combinator in Haskell:
  45.  
  46.    newtype SelfApply t = SelfApply { selfApply :: SelfApply t -> t }
  47.  
  48.    y :: (t -> t) -> t
  49.    y f = selfApply term term
  50.        where term = (SelfApply $ \x -> f (selfApply x x))
  51.  
  52. David
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement