Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type mismatch error in result type

Tags:

f#

I was playing around with writing a result type and assorted functions, and came across a type mismatch error I cannot explain. Here is a minimum example:

type ('a, 'b) result =
    | Success of 'a
    | Failure of 'b list

let apply fr xr =
    match fr, xr with
    | Success f, Success x -> Success (f x)
    | Failure _, Success _ -> fr
    | Success _, Failure _ -> xr
    | Failure a, Failure b -> Failure (List.concat [a; b])

Compiling this code produces the following error:

init.fsx(8,31): error FS0001: Type mismatch. Expecting a
('a,'b) result
but given a
(('c -> 'a),'d) result
The resulting type would be infinite when unifying ''a' and ''b -> 'a'

If you change the apply function according to the below, it compiles correctly:

let apply fr xr =
    match fr, xr with
    | Success f, Success x -> Success (f x)
    | Failure a, Success _ -> Failure a
    | Success _, Failure b -> Failure b
    | Failure a, Failure b -> Failure (List.concat [a; b])

Why does using the matched over value (here fr or xr) not work but constructing a new Failure value does?

like image 271
dumetrulo Avatar asked Jun 14 '16 09:06

dumetrulo


People also ask

How do you fix type mismatch error?

Solution: Try to make assignments only between compatible data types. For example, an Integer can always be assigned to a Long, a Single can always be assigned to a Double, and any type (except a user-defined type) can be assigned to a Variant.

How do I fix type mismatch error in Java?

Resolving The Problem You can avoid the type mismatch by setting the parameter, useAdvancedResponseTypeMapping.

What is a mismatch error?

Sometimes, while writing code, programmers may ask that a value be stored in a variable that is not typed correctly, such as putting a number with fractions into a variable that is expecting only an integer. In such circumstances, the result is a type-mismatch error.


2 Answers

The critical thing to understand here is that the type of a discriminated union concerns all its cases. Even if you "only" reuse instances of Failure from a function parameter as a return value, all return values, including the Success cases, must have the same type as this parameter.

Thus, using fr and xr as return values constrains their types to be identical to apply's return type.

But there's also the line that takes a parameter of Success f to a return value of Success (f x)! If these two are to have the same type, the type of f x must be the type of f! That's a function that returns a function of its own type, no matter how many times you apply it; such an infinite type isn't allowed and causes the compiler error.

By building new instances for the return values, you allow apply's return type to differ from its parameters' types. Then, the compiler can give f and its return value different types, avoiding the infinite function type.

like image 128
Vandroiy Avatar answered Nov 15 '22 08:11

Vandroiy


Here is the error.

In this line:

Success f, Success x -> Success (f x)

you define 'a to be a function type and as a result your return 'a is also a function.

but when you do

| Failure _, Success _ -> fr

this fr has the same function type, but here is unapplied.

In contrast, creating the new object gives it a new type which can use the fact that the success type is now the result of the function in the second case

like image 44
John Palmer Avatar answered Nov 15 '22 08:11

John Palmer