Эти производные работают с polymorphi c структурами данных и применяют пользовательскую функцию ко всем значениям, соответствующим переменным типа этой структуры. Поскольку у вас нет переменных типа, сгенерированная функция map_data
является дефектной, но вполне естественной, поскольку отсутствие переменной типа подразумевает постоянную функцию.
Другими словами, общая структура функции map_x
для некоторых полиморфных c type ('s1, ..., 'sN) x
с переменными типа N
составляет
('s1 -> 't1) -> ... -> ('sN -> 'tN) -> ('s1,...,'sN) x -> ('t1,...,'tN) x
Т.е. для каждой переменной типа она ожидает функцию, которая отображает значения этого типа на какой-то другой тип, так что число аргументов функции map будет N+1
В вашем случае, поскольку у вас есть переменные нулевого типа, нет функций отображения, поэтому у вас просто x -> x
.
Если вы переопределите свой тип как
type 'a data = Row of 'a array | Dim of 'a data array
[@@deriving iter, map, fold, show]
Вы получите map_data
с ожидаемым типом ('a -> 'b) -> 'a data -> 'b data
. Производный даже поймет, что массив является структурой данных, и вернется в нее, например,
let input = Dim [|Row [|1;2;3|]; Row [|3;4;5|]|]
map_data (fun x -> x + 1) input;;
- : int data = Dim [|Row [|2; 3; 4|]; Row [|4; 5; 6|]|]
Конечно, если вам не нужен тип polymorphi c в вашем интерфейсе, вы всегда можете создайте псевдоним типа, например,
type t = float data
и предоставьте map_data как
val map_data : (float -> float) -> t -> t