Description
Description
While experimenting with the idea of combinators, I discovered the following bug with the resolution of generic types:
import sugar
proc bi[A, B](xy: (A, A),
f: (A) -> B): (B, B) =
(f(xy[0]), f(xy[1]))
func bi[A, B, C](x: A,
f: (A) -> B,
g: (A) -> C): (B, C) =
(f(x), g(x))
echo (10, 20).bi((x) => x * x) # Errors with type mismatch
It appears that the Nim compiler cannot resolve which implementation of bi
to use nor the type of x
. It seems to pick bi[A, B, C]
even though the number of arguments does not match. However, if it is actually choosing bi[A, B]
then it is inferring the type of A
incorrectly. Additionally, the error message does not inform the user that the resolution of bi
is ambiguous.
This ambiguity can be resolve by changing the last line to the following:
echo (10, 20).bi((x: int) => x * x)
This change forces the Nim compiler to resolve bi as bi[A, B]
. However, this solution was not clear from the error message.
Nim Version
Nim Compiler Version 1.6.10 [Linux: amd64]
Current Output
main.nim(13, 27) Error: type mismatch: got <(int, int), (int, int)>
but expected one of:
func `*`[T](x, y: set[T]): set[T]
first type mismatch at position: 1
required type for x: set[T]
but expression 'x' is of type: (int, int)
proc `*`(x, y: float): float
first type mismatch at position: 1
required type for x: float
but expression 'x' is of type: (int, int)
proc `*`(x, y: float32): float32
first type mismatch at position: 1
required type for x: float32
but expression 'x' is of type: (int, int)
proc `*`(x, y: int): int
first type mismatch at position: 1
required type for x: int
but expression 'x' is of type: (int, int)
proc `*`(x, y: int16): int16
first type mismatch at position: 1
required type for x: int16
but expression 'x' is of type: (int, int)
proc `*`(x, y: int32): int32
first type mismatch at position: 1
required type for x: int32
but expression 'x' is of type: (int, int)
proc `*`(x, y: int64): int64
first type mismatch at position: 1
required type for x: int64
but expression 'x' is of type: (int, int)
proc `*`(x, y: int8): int8
first type mismatch at position: 1
required type for x: int8
but expression 'x' is of type: (int, int)
proc `*`(x, y: uint): uint
first type mismatch at position: 1
required type for x: uint
but expression 'x' is of type: (int, int)
proc `*`(x, y: uint16): uint16
first type mismatch at position: 1
required type for x: uint16
but expression 'x' is of type: (int, int)
proc `*`(x, y: uint32): uint32
first type mismatch at position: 1
required type for x: uint32
but expression 'x' is of type: (int, int)
proc `*`(x, y: uint64): uint64
first type mismatch at position: 1
required type for x: uint64
but expression 'x' is of type: (int, int)
proc `*`(x, y: uint8): uint8
first type mismatch at position: 1
required type for x: uint8
but expression 'x' is of type: (int, int)
expression: x * x
Expected Output
No response
Possible Solution
- Improved error messaging in this edge case.
- Giving the compiler the ability to resolve the types here.
Additional Information
It is worth noting that a language such as Kotlin can resolve similar constructions:
fun <A, B> bi(pair: Pair<A, A>, f: (A) -> B): Pair<B, B> {
return Pair(f(pair.first), f(pair.second))
}
fun <A, B, C> bi(x: A, f: (A) -> B, g: (A) -> C): Pair<B, C> {
return Pair(f(x), g(x))
}
fun main() {
println(bi(Pair(10, 20), { x -> x * x }))
println("Hello, world!!!")
}