Skip to content

Inconsistent error message between .NET interactive notebooks and VS / FSI session #13921

@bmitc

Description

@bmitc

I'm having a lot of confusing issues with type inference when using type aliases with sequences. The behavior and errors reported differ between Visual Studio, .NET Interactive notebooks, and FSI.

Repro steps

SequentialLogic.zip

  1. See the attached SequentialLogic.ipynb notebook and note the error of

    Error: input.fsx (9,5)-(9,9) typecheck error Value restriction. The value 'Not'' has been inferred to have generic type
    val Not': (Signal -> Signal)
    Either make the arguments to 'Not'' explicit or, if you do not intend for it to be generic, add a type annotation.

    The error does not make any sense to me because Signal -> Signal is exactly the intended type of Not' and is not generic.

  2. See the attached SequentialLogic solution and open Signal.fs in the CPUSimulator project in Visual Studio 2022. Note that Not', And', and so on have no error but Xor' reports the error

    image

    I suppose this error may make a little sense to me given that Signal is a type alias of seq<bit> and that seq can have subtypes (such as list or array, is that correct?). But what doesn't make sense is that Not', And', and so on are defined identically but do not report the same error. Nor do they report the same error as the .NET Interactive notebook.

    Note: I just noticed that if I delete the code after Xor' in the project, the errors show up for all the <operator>' definitions. This is strange to me.

  3. Enter the code into FSI, and you'll get yet another distinct error case for Not' as opposed to the .NET Interactive error and the Visual Studio non-error for Not'.

    > let Not' = liftToSignal1 Not;;
    
      let Not' = liftToSignal1 Not;;
      ----^^^^
    
    stdin(52,5): error FS0030: Value restriction. The value 'Not'' has been inferred to have generic type
        val Not': ('_a -> Signal) when '_a :> Signal
    Either make the arguments to 'Not'' explicit or, if you do not intend for it to be generic, add a type annotation.

Expected behavior

I would say the expected behavior is:

  • Consistently reported errors
  • Errors that make sense (in the case of the .NET Interactive error)
  • Errors that do not adjust when code defined after the problematic code is removed
  • I expected the use of the "lift" functions to be straightforward to avoid having to explicitly define parameters and/or provide additional type annotations. Note that the "lift" functions themselves are explicitly typed.

Actual behavior

Several inconsistent errors as described above.

Known workarounds

Either explicitly type all functions and/or provide parameters. For example, if I define Not' in the .NET Interactive notebook as

let Not' input = liftToSignal1 Not input

the error goes away. This doesn't quite make sense to me given liftToSignal1 is explicitly type annotated, and I don't type annotate input here. Defining Not' as

let Not' : Signal -> Signal = liftToSignal1 Not

also gets rid of the confusing errors.

Related information

Provide any related information (optional):

  • Operating system: Windows 11
  • .NET Runtime kind (.NET Core, .NET Framework, Mono): .NET 6
  • Editing Tools (e.g. Visual Studio Version, Visual Studio): Visual Studio Community 2022, Visual Studio Code with .NET Interactive Notebooks extension, and dotnet fsi

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions