fsprojects / IfSharp

F# for Jupyter Notebooks
Other
442 stars 71 forks source link

Type printing for some functions won't work #153

Closed SLAPaper closed 5 years ago

SLAPaper commented 7 years ago

Description

I'm trying the "Swapping Arguments" example in http://www.tryfsharp.org/Learn/advanced-programming:

In[1]: let swapargs f x y = f y x

the type should has signature of val swapargs : f:('a -> 'b -> 'c) -> x:'b -> y:'a -> 'c

but when I want to print the sig by

In[2]: swapargs

there is no output

while

In[3]: let add a b = a + b
       add
Out[3]: <fun:it@2-1> : (int -> (int -> int))

is what is expected as talked in #125 #131

Repro steps

  1. Step A
let swapargs f x y = f y x
  1. Step B
swapargs

Expected behavior

Out[*]: <fun:it@2-1> : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c

Actual behavior

No output

Known workarounds

use the Intellisense to check the signature of the function

Related information

SLAPaper commented 7 years ago

Update: I checked the possiblyAFuncAsString in https://github.com/fsprojects/IfSharp/blob/99e4fde10158be5af013e126995e03e1679411ae/src/IfSharp.Kernel/Printers.fs#L53 but it works partially when I put the swapargs into it.

In [7]: possiblyAFuncAsString(swapargs.GetType())
Out[7]: "((obj -> (obj -> obj)) -> (obj -> (obj -> obj)))"

Although it doesn't provide the difference between different "obj", at least it print something. But I can't figure out why this string won't output.

cgravill commented 7 years ago

What's happening is that we extract the expression dynamically, see GetLastExpression https://github.com/fsprojects/IfSharp/blob/master/src/IfSharp.Kernel/Evaluation.fs#L68

That isn't the same as what is going on in F# Interactive (which I believe is working from more of the source).

Using the approach we do, causes the evaluation of swapargs to throw an exception concerning value restriction:

Value restriction. The value 'it' has been inferred to have generic type
    val it : ((obj -> obj -> obj) -> obj -> obj -> obj)    
Either make the arguments to 'it' explicit or, if you do not intend for it to be generic, add a type annotation.

which we currently don't display. I'm not sure that displaying it would be a good idea as the error is a side-effect of the way we try to extract expressions.

@dsyme do you have any suggestion of how to handle this?