#types #f#
#типы #f#
Вопрос:
Я пишу функцию F # следующим образом, чтобы вычислить произведение списка чисел с суммой «r».
> let rec proda xs r =
- match xs with
- | [] -> r
- | x::xr -> proda xr (x*r)
- ;;
К моему удивлению, его тип proda
, согласно консоли F #:
val proda : xs:int list -> r:int -> int
Почему тип не proda
val proda : xs:a' list -> r:a' -> a'
Ответ №1:
Предполагается int
, что тип аргумента равен, потому что вы используете *
оператор для объединения элементов списка x * r
. Это определяет тип x
и r
как int
и, следовательно, xs
станет int list
.
Если вы хотите избежать этого, вы могли *
бы заменить функцию, указанную в качестве дополнительного аргумента:
let rec proda f xs r =
match xs with
| [] -> r
| x::xr -> proda f xr (f x r)
Это имеет следующий тип:
val proda : f:('a -> 'b -> 'b) -> xs:'a list -> r:'b -> 'b
Это очень полезная функция, и она включена в основную библиотеку F # как List.fold
(с переключением последних двух аргументов)! Это несколько более общий, потому что результат может быть другого типа, чем элементы списка ( a
против b
), но это простое обобщение того, что у вас есть.
РЕДАКТИРОВАТЬ Вы правы, с которым *
также можно использовать float
. Чтобы поддержать это, вам нужно будет создать функцию inline
. Это немного сложно, потому что вы не можете сделать это с помощью рекурсивной функции, поэтому вам нужно добавить вложенную рекурсивную функцию:
let inline proda xs r =
let rec loop xs r =
match xs with
| [] -> r
| x::xr -> loop xr (x*r)
loop xs r
С помощью встроенных функций компилятор может вывести «ограничения статического члена», что, по сути, является способом сказать «любой тип, который поддерживает *
«. Синтаксис немного затянутый:
val inline proda :
xs: ^a list -> r: ^b -> ^b
when ( ^a or ^b) : (static member ( * ) : ^a * ^b -> ^b)
Комментарии:
1. Спасибо. Тем не менее, «*» не ограничивается целыми числами. Это и для поплавков тоже! Например, «fun x-> x * 2.8» — это функция типа float-> float .
2. Только что обнаружил, что «fun x y -> x * y» имеет тип «int -> int -> int». Удивлен.
3. Вы правы — вы можете
*
работать как с плавающими, так и с целымиinline
числами. См. Редактирование.