Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type inference rules

Tags:

syntax

types

f#

I tried to make a function that takes two characters, takes their ASCII value and returns their XOR. Of course, that works:

> let a, b = '#', '%' in (int a) ^^^ (int b);;
val it : int = 6

This however makes a function that takes integers, which is not the case here.

> let xor a b  = (int a) ^^^ (int b);;                        

val xor : a:int -> b:int -> int

As expected, I can't call this function on previous arguments:

> let a, b = '#', '%' in xor a b;;

  let a, b = '#', '%' in xor a b;;
  ---------------------------^

/home/cos/stdin(121,28): error FS0001: This expression was expected to have type
    int    
but here has type
    char    

Why does it happen? How to specify directly the types of arguments?

like image 388
enedil Avatar asked Jan 30 '26 06:01

enedil


1 Answers

This is how:

let xor (a: char) (b: char)  = (int a) ^^^ (int b)

You can also mark it inline to get a generic function

let inline xor a b  = (int a) ^^^ (int b)

This will have the type

val inline xor :
  a: ^a -> b: ^b -> int
    when  ^a : (static member op_Explicit :  ^a -> int) and
          ^b : (static member op_Explicit :  ^b -> int)

and thus work for anything that can be converted to int.

The reason that

let xor a b  = (int a) ^^^ (int b)

is inferred to have type int -> int -> int is that for arithmetic operations, F# infers the type int by default (See language specification, page 13)

like image 160
nilekirk Avatar answered Feb 02 '26 01:02

nilekirk