Skip to content

Incorrect error message with applicative Computation Expressions  #12607

@michaeloyer

Description

@michaeloyer

When creating an Applicative Computation Expression (CE) if you forgot to include the function parameter at the end of a BindN method, the error message.

Here's a code snippet I have using VSCode with the Ionide extension.


NOTE: This computation expression is wrong, if you came to this github issue trying to figure out how a BindN method should be structured and executed, ignore the following snippet and look below).


type OptionBuilder() = 
    member _.Bind(option, binder) = Option.bind binder option
    member _.Return(value) = Some value
    member _.Bind3(o1, o2, o3) = // Wrong signature
        match o1, o2, o3 with
        | Some v1, Some v2, Some v3 -> Some(v1, v2, v3) // Wrong return
        | _ -> None
    
let option = OptionBuilder()

option {
    let! a = Some 1
    and! b = Some 2
    and! c = Some 3

    return a + b + c // This will never get hit by the CE above
}

If possible attach a zip file with the repro case. This often makes it easier for others to reproduce.
The zip file should ideally represent the situation just before the call/step that is problematic.

Expected behavior

An error message on let! a = ... that reads:

The member or object constructor 'Bind3' takes 4 argument(s) but is here given 3. The required signature is 'member OptionBuilder.Bind3: o1: 'a0 option * o2: 'a1 option * o3: 'a2 option * ('a0 * 'a1 * 'a2 -> 'a3 option) -> 'a3 option'

Actual behavior

An error message on let! a = ... that reads:

The member or object constructor 'Bind3' takes 3 argument(s) but is here given 4. The required signature is 'member OptionBuilder.Bind3: o1: 'a0 option * o2: 'a1 option * o3: 'a2 option -> ('a0 * 'a1 * 'a2) option'.

Known workarounds

N/A

Related information

VS Code, Ionide Extension

Correct Version of the Computation Expression:

type OptionBuilder() = 
    member _.Bind(option, binder) = Option.bind binder option
    member _.Return(value) = Some value
    member _.Bind3(o1, o2, o3, f) =
        match o1, o2, o3 with
        | Some v1, Some v2, Some v3 -> f (v1, v2, v3)
        | _ -> None
    
let option = OptionBuilder()

option {
    let! a = Some 1
    and! b = Some 2
    and! c = Some 3

    return a + b + c
} // Some 6

option {
    let! a = Some 1
    and! b = Some 2
    and! c = None

    return a + b + c
} // None

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-Diagnosticsmistakes and possible improvements to diagnosticsBugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.

    Type

    Projects

    Status

    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions