none
How is this possible? RRS feed

  • Question

  • Hello,

    I'm using Visual Studio 2010 Shell, but even if I step into, I can't understand very well how does this work:

    let adicA (x, y) = x + y
    let adicB x y = adicA(x, y)
    
    let adic_3 = adicB 3
    adic_3 4
    |> printfn "%d"

    While stepping into, it goes back and forth, and suddenly '3' and '4' appear as 'x' an 'y'. Can anyone give me a detailed explanation on how does this work?


    "Penso, logo existo" - René Descartes
    "A produção de muitas coisas úteis resulta em muitas pessoas inúteis" - Karl Marx
    "Vive como se fosses morrer amanhã, aprende como se fosses viver para sempre" - Mahatma Gandhi

    João Miguel


    • Edited by JMCF125 Saturday, January 5, 2013 1:49 PM typo
    Saturday, January 5, 2013 1:14 PM

Answers

  • If you send adicA function into F# interactive you'll see it's signature:

    val adicA : x:int * y:int -> int

    It takes tuple x * y and returns int.

    For adicB it F# interactive gives:

    val adicB : x:int -> y:int -> int

    Which means it's quite opposite.


    Petr

    • Marked as answer by JMCF125 Saturday, January 5, 2013 6:25 PM
    Saturday, January 5, 2013 5:24 PM

All replies

  • Let start with first line:

    let adicA (x,y) =x +y

    It is a definition of function with name 'adicA' that takes a tuple (pair) of two integer parameters and returns their sum

    Second line:

    let adicB x y =adicA(x,y)

    It is also a definition of function with name 'adicB' that takes two separate parameters and returns a result of application of function 'adicA' to parameters of function adicB.

    Next line:

    let adic_3 =adicB 3

    This is also a definition of function with name 'adic_3' which is the result of PARTIAL application of function adicB to one of its parameters (integer 3). Partial application in F# is a feature that is broadly used in many functional programming languages. It uses property of functions named 'currying': i.e. application of function with several parameters is equivalent to sequential application of several functions each with one of these parameters. You can read more about currying and partial application here: http://en.wikibooks.org/wiki/F_Sharp_Programming/Higher_Order_Functions (section 'How currying works') and here: http://stackoverflow.com/questions/1352855/in-functional-programming-what-is-currying

    Basically you could replace this line by its equivalent: let adic_3 z = adicB 3 z

    so the call of adic_3 is equivalent to the call of adicB with one 'fixed' parameter equals 3

    Next line:

    adic_3 4

    defines value that is the result of application of function 'adic_3' to integer 4 which is '7'.

    If you want to know how it is implemented 'under the hood' you could use utility like 'ildasm' to see how it works at .Net MSIL level.

     Hope it helps


    Petr



    • Edited by Plepilov Saturday, January 5, 2013 4:49 PM
    Saturday, January 5, 2013 4:47 PM
  • Basically you could replace this line by its equivalent: let adic_3 z = adicB 3 z

    so the call of adic_3 is equivalent to the call of adicB with one 'fixed' parameter equals 3

    Next line:

    adic_3 4

    defines value that is the result of application of function 'adic_3' to integer 4 which is '7'.


    Thanks for the replie. I know about currying; actually, I'm asking this because it doesn't seem to fit in the "currrying scenario".

    The part I don't understand is how it calls adicB without the rest of the tuple; because (I think), for the compiler, adicA returns a function with the 'x' argument that returns a function with the 'y' argument, that returns the addition of x and y. When a function is passed, its single argument becomes a constant. As such, I'm aware adicA could be rewritten like this:

    let adicA = fun x -> fun y -> x + y

    However, adicB is a function with an argument that is a tuple, and not with two arguments. How can it be curried like above with adicA? If the compiler can curry it, then I can currry it, right? How?This is what I cannot understand and would like you to explain.


    "Penso, logo existo" - René Descartes
    "A produção de muitas coisas úteis resulta em muitas pessoas inúteis" - Karl Marx
    "Vive como se fosses morrer amanhã, aprende como se fosses viver para sempre" - Mahatma Gandhi

    João Miguel

    Saturday, January 5, 2013 5:12 PM
  • If you send adicA function into F# interactive you'll see it's signature:

    val adicA : x:int * y:int -> int

    It takes tuple x * y and returns int.

    For adicB it F# interactive gives:

    val adicB : x:int -> y:int -> int

    Which means it's quite opposite.


    Petr

    • Marked as answer by JMCF125 Saturday, January 5, 2013 6:25 PM
    Saturday, January 5, 2013 5:24 PM
  • What an idiot I've been! I don't know how did I switch that! This is a revisistated subject for me, I did remember thinking of this and then "Well, it is obvious", but I didn't remember how I got to that very conclusion, so I just wrote it and posted it.

    Next time, I'll try to think before I replie (my replie sounds like I haven't read my own post!) and before I post the question.

    Reading your replie was a slap in the face, an wakening from my non-sense, which was just what I needed. Thank you (and sorry for wasting) your time.


    "Penso, logo existo" - René Descartes
    "A produção de muitas coisas úteis resulta em muitas pessoas inúteis" - Karl Marx
    "Vive como se fosses morrer amanhã, aprende como se fosses viver para sempre" - Mahatma Gandhi

    João Miguel

    Saturday, January 5, 2013 6:25 PM