#K is the constant function. K(x,y) = x
1 messages · Page 1 of 1 (latest)
I'm trying to wrap my head around this, but I don't see how you ever get anything out of these functions or their combinations, or why K has two arguments when all it does is relay one of them. K seems just to be like a factorio wire that can only carry one signal. And I don't see how S works given that it seems to need a one argument function and none are defined
Well for example, you can build the identity function as SKK.
You can similarly build whatever other functions you want. The program I’ve linked builds a singly-linked list of integers that match the ASCII values of »hello world«.
S(K)(K)
Sorry, we often omit function application parentheses in these kinds of calculations, because it fills everything with parentheses
So SKK is S(K, K) is (S(K))(K)
You can see the definition of K at the very top in plain Javascript in the file
But S only has 2 operands there?
(S applied to K) applied to K
How does S apply to K if K gives a constant and S needs two functions and a constant
Basically you just succ-ed 0 until you got the ascii values for hello world, yeah?
Basically the first argument is K and the second argument is K and the third argument is now irrelevant
Simpler example: the "+" operator can be thought of as a function that adds 2 numbers
So for example, (+) 2 3 = 5, follow?
Follow
We can turn this into a function that takes one argument by defining (+ 2) y = (+) 2 y
Follow?
Follow
So (+2) 3 = 5
So that's basically what he's done with the SKK stuff
SKK x = S (K) (K) x etc.
You can do it by hand! Just insert definitions.
SKKx (apply S rule) = Kx(KKx) => (apply K rule) = x
SKS would also be the identity. In fact, SKy is the identity for any y now that I look at it.
I thought you were just being obtuse to sound smart lol
This is called partial function? application? something like that
How could x + y be achieved with S and K logic? You take x and apply the +y function, but how do you define a + operator?
or a +y operator
You see the succ function?
That's basically a +1, so to do x + y he just did succ y times
You could define (+3) _ = (succ(succ(succ(_)))
If you wanted you could do a recursive definition so
(+) x _
x = 1: succ _
else: (+) <x - 1> _
I see that, how is succ defined here?
At the bottom, just directly as +1
There's some syntactical sugar here where basically f x = (operations) x is just written as f = (operations) but I've chosen to make it explicit by f _ = (operations) _ just to be clear
Eh well top and bottom are going to be a bit more grey depending on who you ask but you're right that it's "bottom"
I had kinda forgotten that real actual things were being put into the S and K stack, rather than just pure S and K
when u write SKKx here is that shorthand for
S(K, K, x)?
Yeah, which is why he just defined hello = (definition) instead of hello _ = (definition) _
It probably doesn't help that I'm unfamiliar with the syntax used to define the functions in the python file and I'm wholly unfamiliar with javascript
Here's an example in Haskell which you are almost certainly unfamiliar with the syntax of but should be still quite understandable https://wiki.haskell.org/Partial_application
@proper marten
Uh, the notation you need to know here is that the rightmost type is the function type and everything above is an argument
More accurately, SKKx is shorthand for S(K)(K)(x).
All functions take exactly one argument. »Multi-arg functions« are functions that take one argument and return another function that takes another argument.
add(x,y) can be thought to take one argument, to return an add-y-to-that function.
So that add(5,x) = add5(x).
So Int -> Int -> Int takes 2 ints and returns another Int, but Int -> (Int, Int) takes an Int and returns an (Int, Int), and Int -> (Int -> Int) takes an Int and returns an (Int -> Int) (which itself is something that takes an Int and returns another Int)
In other words, if you leave away an argument, it remains left open. :D
Basically the idea for this kind of thing is that you're reducing the arity (which is the number of arguments a function takes)
Which is what I tried to illustrate over here
Thanks I see that now, there the definiton of addOne doesn't seem to have an explicit argument? does js "know" that it is expecting an argument because add takes 2 and 1 is already provided?
For the more readable version of the SK hello world, have a look at the original lambda calculus source here
Well Haskell knows that for sure, that's the language the page I linked you in is written in. I don't know enough about JS to say for sure but it would seem so
Oh sorry I missed that, I'm unfamiliar with both
JS doesn’t have automatic currying. Haskell is the only somewhat popular language that has it.
Yeah, this concept of combining/splitting arguments is called currying/uncurrying, not because of the food but because of the mathematician Haskell Curry (who Haskell is named after)
In Haskell, answering how many arguments a function takes is
- hard for the first couple of attempts
- easy for the next 1000 hours
- later you get into implementation details and questions about how many arguments
foo x = \y -> …takes and it becomes complicated again, but luckily that’s veeeery rarely relevant
All those let [...] (lambda [name] statements define a function [name] as [...]?
Important distinction if you're going to look into this more, is that currying is related to but is not partial application, which is what we're doing
Where are these let etc. things you're seeing?
let is literally a named function itself, defined below :-D
let is λ value body. body value
Note how similar let x = y in body is to (lambda x: body)(y)
That’s all there is to it
Did not expect to see another haskeller here... but somehow it's unsurprising to be the person who's doing all this SKK stuff
It makes the program more readable, and variable names in my lambda calculus is very simple. Anything except whitespace, parentheses and lambda can be used. See the variables literally named 2 and so on :-D
Hello I’m quchen I’m the one who made Applicative a superclass of Monad in GHC nice to meet you :-D
Ah, the classic haskell avoidance of $
Very nice to meet you, and no wonder you have a lambda in your name lol
Implementing infix is hard so I didn’t do it
I was introduced to the language by Philip Wadler, but I can't claim to be anything more than a student in his lectures
The lambda in my name is unsurprisingly generated with Haskell. I also wrote a compiler to GCode and literally laser-engraved it into my laptop’s lid. :-D
How’s that for academic language! haha
Got the code for that somewhere? I've never been able to get into graphics etc. with Haskell, I've just stuck to strictly pure stuff and never really did anything in main() lol
Well it's glad to hear you're haskelling too because that means my understanding of what you were trying to do is correct lol
btw you can surround your links with angle brackets to prevent the embeds from appearing
Not to be a philistine but if you can define functions in hs, why did you need to define let, and if you can't define functions in hs, how did you define let?
I’m not that deep into Haskell anymore I’m afraid, I have too many other hobbies, and I’ve worked with it quite excessively for a while. I do still organize the Munihac (Haskell hackfest in Munich)
Let is basically a way to define local functions, in other words functions within functions
What I showed you wasn’t Haskell, it is a custom language
Oh okay
No worries, just glad to see another person entirely! I'm currently working on trying my hand at some recursive solvers in Haskell but that's strictly hobbytime thing so it'll be a long time before I can show it off
When I do though I'd love to talk about it with you
Sure! :-)
Assumed because of the .hs file extension
Ah okay, very cool
The compiler is in Haskell, but it takes as input the long string (green marks), parses it, converts it, prints it out to e.g. Javascript
I could have opened a file with the source as well (like all the normal compilers and pretty much any programs do), I just wanted to have it all in one place.
The wrapper could have been written in any language, I just liked Haskell. But it’s very much possible to do the same program in whatever, e.g. JS.
Okay so that file is a lambda calc language and a compiler to convert that language to haskell?
No, to convert it to whatever you want.
See it this way. g++ is a compiler written in c++ that reads text files containing c++ and converts them to assembly.
my program is written in Haskell and reads text written in my own language and converts them to Javascript.
I’ve also written a to-haskell backend, but the output of the Javascript version is the nicest.
That's really cool, thank you. I currently have some free time and am greatly enjoying nand on your recommendation
Maybe a shorter example of how these things work.
Parts of me wish I'd done this sort of thing as my degree, but I think I like it more as a side-interest
The input is λ x. x
The program parses that to internal data structure EAbs "x" (EVar "x")
It then converts it to a different notation (DeBruijn indices), Abs (Var 1)
It then converts that to a different notation, App (App S K) K
It then converts that to a different notation (Javascript) S(K)(K)
It then converts that to string and prints it
Compilers are all about converting stuff ;-)
I’m a physicist, so this is all a side interest spiralled out of control for me ;-)
Definitely spiralled a lot out of control if you reached the point of being the person who made Applicative.Monad
That was mostly political though. The actual implementation was adding the => and fixing some 150 non-applicative Monad instances.
Hahah making it official is an extremely useful thing even if only in appearance
And making it compatible and convincing others it’s a good idea.
I’m happy that I did it but today I’m not sure I had the the energy ;-)
So... any thoughts on my idea that Spoilage is basically asking you to apply the Maybe monad to all your builds?
Nandgame is excellent, doesn’t take too much time, is a game, teaches you a lot, and solutions are available.
Maybe is a type. It is an example of a monad, but you don’t say »the Int Num«, do you? ;-)
I might, depending on the context 😛
I guess you can see spoilables as Maybe X
Sometimes Int is integer, sometimes Integral, etc.
That is, spoilable-taking factories are.
Yeah that's basically what I did, it was a bit of a random click but I haven't had anyone aware enough about monads to know how accurate my opinion was!
random click, random thought
This isn’t about monads. It would still apply if you deleted the Monad instance.
All you need is Maybe a = Nothing | Just a, no instances
But it’s a personal pet peeve, like when people say the IO monad. Don’t worry too much about it.
Hey, no worries 🙂 Just glad that someone out there understands enough to do more than go "yeah that seems right"
Also more motivation for me to continue getting the practice with monads (and non-monads) that I want to
Monads are hard until you understand them, then they become easy and you lose the ability to explain them
It’s not long, it’s not a tutorial, it’s what I think is the best advice
FWIW when I learned about monads it was different – I thought »yeah you can do that but why«. It’s usually either that or confusion. Both resolve after a while. :-D