fsprojects / IfSharp

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

Inferred Typing Fail across Cells #141

Closed boustrephon closed 7 years ago

boustrephon commented 7 years ago

Description

I have defined three functions in two cells. In my original version I put the definition of addTuple in the first cell, and mu6 and fullSecProp2D in the second. However, when I did so, I got a type error as below.

Repro steps

If you copy my code into a notebook, you should get the same problem.

let addTuple6 (a, b, c, d, e, f) (g, h, i, j, k, l) = (a+g,b+h,c+i,d+j,e+k,f+l)

let mu6 (x1, y1) (x2, y2) = 
   let a = (x1 * y2 - x2 * y1) / 2.0
   (a, 
       (x1 + x2) * a / 3.0, 
       (y1 + y2) * a / 3.0,
       (y1**2.0 + y1*y2 + y2**2.0) * a / 6.0,
       (x1**2.0 + x1*x2 + x2**2.0) * a / 6.0,
       (x1*y2 + 2.0*x1*y1 + 2.0*x2*y2 + x2*y1) * a / 12.0)

let fullSecProp2D ptLst = 
   let rec recSecProp2D ptLst = 
       match ptLst with 
       | [a] -> (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
       | b::c -> addTuple6 (mu6 b c.Head) (recSecProp2D c)
       | _ -> (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
   let (a, b, c, d, e, f) = recSecProp2D ptLst
   (a, b/a, c/a, d, e, f)

Expected behavior

I would expect this to simply compile and give no error.

Actual behavior

input.fsx(14,18): error FS0001: Type mismatch. Expecting a
    'float * float * float * float * float * float'    
but given a
    'int * int * int * int * int * int'    
The type 'float' does not match the type 'int'

Line 14 corresponds to | b::c -> addTuple6 (mu6 b c.Head) (recSecProp2D c)

Known workarounds

  1. Move all code into a single cell.
  2. Specify types addTuple6 (a:float, b:float, c:float, d:float, e:float, f:float) (g, h, i, j, k, l)
  3. Multiply by 1.0 to force type inference to assume floats

Related information

cgravill commented 7 years ago

This is a non-ideal interaction between the cell-by-cell basis of Jupyter Notebooks and F# needing a fixed type for your function as specified. We send each cell to the F# compiler as an individual unit so when you split addTuple6 to its own cell, it has to resolve the types, which by default with + is going to go with int.

A good solution for this is inline https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/inline-functions which allows the compiler to generate specialised versions as need.

If you do that with addTuple6 you'll be able to split your code to multiple cells

let inline addTuple6 (a, b, c, d, e, f) (g, h, i, j, k, l) = (a+g,b+h,c+i,d+j,e+k,f+l)

Hope this is useful.

cgravill commented 7 years ago

I'm going to close this issue as it is an interaction between F# type specialisation and Jupyter's cell-by-cell approach. If anyone has an alternative feel free to re-open. Hope inline is useful.

boustrephon commented 7 years ago

Thanks... much appreciated.

boustrephon commented 7 years ago

Thanks. It worked. Much appreciated...

On 19 April 2017 at 22:53, Colin Gravill notifications@github.com wrote:

I'm going to close this issue as it is an interaction between F# type specialisation and Jupyter's cell-by-cell approach. If anyone has an alternative feel free to re-open. Hope inline is useful.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/fsprojects/IfSharp/issues/141#issuecomment-295297928, or mute the thread https://github.com/notifications/unsubscribe-auth/ANW8ng6kLaFDdpmskMA66xbyThJ9w7K-ks5rxh_rgaJpZM4Msq-G .