Skip to content

Type annotation adjacency warning doesn't consider operator names #774

Open

Description

@frankshearar

In this snippet,

type Digit<'a> = 'a list
type FingerTree<'a> =
    | Empty
    | Single of 'a
    | Deep of Digit<'a> * FingerTree<Node<'a>> * Digit<'a>

let rec (<<)<'a> (a: 'a) (tree: FingerTree<'a>): FingerTree<'a> =
    match tree with
    | Empty -> Single a
    | Single b -> Deep ([a], Empty, [b])
    | Deep ([b; c; d; e], m, suffix) -> Deep ([a; b], (Node3 (c, d, e)) << m, suffix)
    | Deep (prefix, m, suffix) -> Deep (List.append [a] prefix, m, suffix)

the compiler warns that "Type parameters must be placed directly adjacent to the type name". Presumably that's because the method name is surrounded by ()s.

(I need the <'a> because the function takes a FingerTree<'a> but the recursion takes a FingerTree<Node<'a>>.)

If I make the operator a function, instead --

    let rec addToFront<'a> (a: 'a) (tree: FingerTree<'a>): FingerTree<'a> =
    match tree with
    | Empty -> Single a
    | Single b -> Deep ([a], Empty, [b])
    | Deep ([b; c; d; e], m, suffix) -> Deep ([a; b], addToFront (Node3 (c, d, e)) m, suffix)
    | Deep (prefix, m, suffix) -> Deep (List.append [a] prefix, m, suffix)

-- then everything works.

Activity

  1. drvink commented on Dec 8, 2015

    @drvink
    Contributor

    I ran into this previously too; it's the same as issue #396. The solution is to do this instead:

    let rec ``<<``<'a> blahblah =
  2. frankshearar commented on Dec 8, 2015

    @frankshearar
    Author

    Hm, it does remove the squigglies... but then I'm defining a function, not an operator. I can't say `1 << myTree``. It's not a massive train smash: it just seems like an unnecessary wart.

  3. drvink commented on Dec 8, 2015

    @drvink
    Contributor

    That is true--it doesn't really solve the problem the way you (and I) wanted--but agreed; if it can be fixed without breaking existing code, it would be nice, since it certainly seems unintentional and not particularly desirable that it doesn't work as one would expect. (sorry for the noise, just my two cents!)

  4. PatrickMcDonald commented on Dec 8, 2015

    @PatrickMcDonald
    Contributor

    As a workaround, would something like the following work?

    let rec addToFront<'a> (a: 'a) (tree: FingerTree<'a>): FingerTree<'a> =
        match tree with
        | Empty -> Single a
        | Single b -> Deep ([a], Empty, [b])
        | Deep ([b; c; d; e], m, suffix) -> Deep ([a; b], addToFront (Node3 (c, d, e)) m, suffix)
        | Deep (prefix, m, suffix) -> Deep (List.append [a] prefix, m, suffix)
    
    let (<<) = addToFront
    
  5. dsyme commented on Dec 8, 2015

    @dsyme
    Contributor

    You likely don't need the <'a> at all - it can be inferred. You could also use let op_LessLess<'a> ...

  6. frankshearar commented on Dec 9, 2015

    @frankshearar
    Author

    @PatrickMcDonald That's a clever idea, and does indeed work. Thanks!

    @dsyme It can't be inferred because the recursive call is Finger<Node<'a>>, so type inference complains that "The resulting type would be infinite when unifying ''a' and 'Node<'a>'". But using op_LessLess<'a> does do the trick, with a small wrinkle:

    let rec op_LessLess<'a> (a: 'a) (tree: FingerTree<'a>): FingerTree<'a> =
        match tree with
        | Empty -> Single a
        | Single b -> Deep ([a], Empty, [b])
        | Deep ([b; c; d; e], m, suffix) -> Deep ([a; b], op_LessLess (Node3 (c, d, e)) m, suffix)
        | Deep (prefix, m, suffix) -> Deep (List.append [a] prefix, m, suffix)

    The wrinkle is that the recursive call has to use op_LessLess not <<, or the compiler thinks I'm calling the default << operator. But making the parser special-case the equality of "op_LessLess" with "<<" doesn't seem like a win to me.

  7. added
    Impact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.
    on Jan 8, 2016
  8. added this to the Unknown milestone on Aug 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-Compiler-Syntaxlexfilter, indentation and parsingBugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.

    Type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions