OOP exercise with closures

First, thanks for all the help you've offered. Often enough, it's so much that it takes me time to sift through all the good stuff. Thanks again. Okay, I'm in Lesson 10 of *Get Programming with Haskell * and we're creating an OOP-like world with closures. The first step is a cup object with one attribute, its ounce size. Here's a "constructor" cup :: t1 -> (t1 -> t2) -> t2 cup flOz = \message -> message flOz so this returns upon use
myCup = cup 6
myCup which has "internally" a lambda function (\message -> message) 6 waiting, correct? Now a "method" getOz aCup = aCup (\foz -> foz) creates a closure on the lambda function (\foz -> foz) . So upon calling
getOz myCup 6
I'm guessing myCup (\foz -> foz) was evaluated, but I don't understand how the 6 that went in as the bound variable in the constructor came out again with getOz. As I understand it, the cup constructor creates a closure around the given bound argument flOz -- which is confusing because I thought closures "carried" free variables, not bound variables. Perhaps the getOz lambda function (\foz -> foz) replaces completely the (\message -> message) lambda function? So the constructor could have been written cup flOz = (\message -> message) flOz In any case I'm shaky on how A) cup 6 sets up/stores the 6 in the creation of myCup and then how getOz pops it out again. LB

Il 29 dicembre 2020 alle 15:43 Lawrence Bottorff ha scritto:
Okay, I'm in Lesson 10 of *Get Programming with Haskell * and we're creating an OOP-like world with closures. The first step is a cup object with one attribute, its ounce size. Here's a "constructor"
cup :: t1 -> (t1 -> t2) -> t2 cup flOz = \message -> message flOz
so this returns upon use
myCup = cup 6
myCup which has "internally" a lambda function
(\message -> message) 6
waiting, correct?
Not exactly. `myCup` is a function with takes another function as input λ> :t myCup myCup :: (Integer -> t2) -> t2 and the body looks like this \f -> f 6 `\f -> f 6` is different from `(\f -> f) 6`!
Now a "method"
getOz aCup = aCup (\foz -> foz)
creates a closure on the lambda function (\foz -> foz) . So upon calling
getOz myCup 6
I'm guessing myCup (\foz -> foz) was evaluated, but I don't understand how the 6 that went in as the bound variable in the constructor came out again with getOz.
To recap, `myCup` expands to: myCup cup 6 \message -> message 6 Now, applying `getOz` to it… getOz myCup myCup (\foz -> foz) (\message -> message 6) (\foz -> foz) (\foz -> foz) 6 6

Thanks! Since I studied lambda calc a bit I understand the steps
(\message -> message 6) (\foz -> foz)
(\foz -> foz) 6
6
But this is so bizarre! To have a "constructor" that creates an instance,
which is then really a holder of a lambda calculation is a mind-bender.
On Tue, Dec 29, 2020 at 4:07 PM Francesco Ariis
Il 29 dicembre 2020 alle 15:43 Lawrence Bottorff ha scritto:
Okay, I'm in Lesson 10 of *Get Programming with Haskell * and we're creating an OOP-like world with closures. The first step is a cup object with one attribute, its ounce size. Here's a "constructor"
cup :: t1 -> (t1 -> t2) -> t2 cup flOz = \message -> message flOz
so this returns upon use
myCup = cup 6
myCup which has "internally" a lambda function
(\message -> message) 6
waiting, correct?
Not exactly. `myCup` is a function with takes another function as input
λ> :t myCup myCup :: (Integer -> t2) -> t2
and the body looks like this
\f -> f 6
`\f -> f 6` is different from `(\f -> f) 6`!
Now a "method"
getOz aCup = aCup (\foz -> foz)
creates a closure on the lambda function (\foz -> foz) . So upon calling
getOz myCup 6
I'm guessing myCup (\foz -> foz) was evaluated, but I don't understand how the 6 that went in as the bound variable in the constructor came out again with getOz.
To recap, `myCup` expands to:
myCup cup 6 \message -> message 6
Now, applying `getOz` to it…
getOz myCup myCup (\foz -> foz) (\message -> message 6) (\foz -> foz) (\foz -> foz) 6 6
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (2)
-
Francesco Ariis
-
Lawrence Bottorff