Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler outputs unusable type error containing stuff like ^?2863761 #9717

Closed
realvictorprm opened this issue Jul 19, 2020 · 5 comments
Closed

Comments

@realvictorprm
Copy link
Contributor

See title

Repro steps

Try compiling this code:

type Adjazenzliste< ^Node, ^Weight when  ^Node : comparison and ^Weight : comparison and ^Weight : (static member (+) : ^Weight * ^Weight -> ^Weight) and ^Weight : (static member Zero : ^Weight)> = Map< ^Node, ( ^Node * ^Weight) seq>

type MaybeBuilder() =

    member this.Bind(x, f) = 
        match x with
        | None -> None
        | Some a -> f a

    member _.Zero() = None

    member this.Return(x) = 
        Some x
   
let maybe = new MaybeBuilder()

let inline dijkstra< ^Node, ^Weight when ^Node : comparison and ^Weight : comparison and ^Weight : (static member (+) : ^Weight * ^Weight -> ^Weight) and ^Weight : (static member Zero : ^Weight)> (startNode: ^Node) (endNode: ^Node) (graph: Adjazenzliste< ^Node, ^Weight>) =
    let nodes = graph |> Map.toSeq |> Seq.map (fun (key, _) -> key)
    let n = nodes |> Seq.length
    let initialDistances =
        nodes
        |> Seq.map(fun node -> node, None)
        |> Map.ofSeq
        |> Map.add startNode (Some LanguagePrimitives.GenericZero< ^Weight>)
    let initialPredecessors = nodes |> Seq.map(fun node -> node, None) |> Map.ofSeq

    let mutable unvisitedNodes = nodes |> Set.ofSeq
    let mutable dist = initialDistances
    let mutable prev = initialPredecessors

    while unvisitedNodes |> Set.isEmpty |> not do
        let (currentNode, nodeDistance) =
            // next unvisited node with min distance
            dist
            |> Map.toSeq
            |> Seq.filter(fun (node, _) -> unvisitedNodes |> Set.contains node)
            |> Seq.choose(fun (node, value) -> value |> Option.map(fun value -> node, value))
            |> Seq.minBy (fun (_, value) -> value)
        unvisitedNodes <- unvisitedNodes |> Set.remove currentNode

        let neighbours = graph.[currentNode]
        
        for (neighbour, weight) in neighbours do
            let alt = LanguagePrimitives.GenericZero< ^Weight> + nodeDistance 
            maybe {
                let! neighbourDistance = dist.[neighbour]
                if alt < neighbourDistance then
                    dist <- dist |> Map.add currentNode (Some alt)
                    prev <- prev |> Map.add currentNode (Some neighbour)
                    return ()
                else return ()
            } |> (function Some _ -> () | None -> failwithf "Internal error for node %A with neighbour %A" currentNode neighbour)
    
    let rec extractPath node path =
        let newPath =  seq { yield! path; yield node }
        if node = endNode then Some newPath
        else
            match prev.[node] with
            | Some pre -> extractPath pre newPath
            | None -> None
    extractPath startNode Seq.empty

Expected behavior

Should compile or print out a better error message

Actual behavior

Compiler spits out:

error FS0001: A type parameter is missing a constraint 'when ( ^Weight or  ^?2863761) : (static member ( + ) :  ^Weight *  ^?2863761 ->  ^?2863762)'

Known workarounds

None so far

Related information

Also fails in sharplab.

Provide any related information (optional):

  • Operating system: Windows 10
  • .NET Runtime kind (.NET Core, .NET Framework, Mono): .NET 5.0.100-preview.3.20216.6

PS:

Please ignore how bad my code is 😂

@abelbraaksma
Copy link
Contributor

That reminds me of this, basically the same situation, I think: #3508.

@realvictorprm
Copy link
Contributor Author

Side note, if you replace the generic part with e.g. int it compiles fine.

@realvictorprm
Copy link
Contributor Author

I somehow have the feeling that this stuff is related to basic members which are expressed all over via SRTP (like get_Zero and op_Add) as these things are the only special thing I'm doing here.

@cartermp
Copy link
Contributor

There are other issues tracking this so I'll mark it as a duplicate but link it up with #9633 for traceability

@abelbraaksma
Copy link
Contributor

Just chiming in after 4 years: I can confirm that this behavior has since been resolved in public releases of F#. The code of the OP does not show errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants