Можно ли выразить walk
в системе типов ML?
val walk : range list -> (real -> real -> unit) -> unit
val walk : range list -> (real -> real -> real -> unit) -> unit
Одно и то же значение не может существовать с обоими этими типами в ML.
Мы можем легко генерировать значения для каждого из желаемых типов.
type range = real * real * int
signature WALK =
sig
type apply
val walk : range list -> apply -> unit
end
structure Walk0 : WALK =
struct
type apply = unit
fun walk _ _ = ()
end
functor WALKF (Walk : WALK) : WALK =
struct
type apply = real -> Walk.apply
fun walk ((low, high, steps)::rs) f =
let fun loop i =
if i > steps then () else
let val x = low + (high - low) * real i / real steps
in (Walk.walk rs (f x); loop (i + 1)) end
in loop 0 end
end
struture Walk1 = WALKF(Walk0)
struture Walk2 = WALKF(Walk1)
struture Walk3 = WALKF(Walk2)
При этом существуют следующие значения с желаемыми типами.
val Walk0.walk : range list -> unit -> unit
val Walk1.walk : range list -> (real -> unit) -> unit
val Walk2.walk : range list -> (real -> real -> unit) -> unit
val Walk3.walk : range list -> (real -> real -> real -> unit) -> unit
Тогда вам нужно только написать
val _ = Walk2.walk [y_axis, x_axis] do2D
val _ = Walk3.walk [z_axis, y_axis, x_axis] do3D
Чтобы использовать один и тот же walk
для каждой размерности, вам необходимо использовать один и тот же тип для каждой размерности.
fun walk nil f = f nil
| walk ((low, high, steps)::rs) f =
let fun loop i =
if i > steps then () else
let val x = low + (high - low) * real i / real steps
in (walk rs (fn xs -> f (x::xs)); loop (i + 1)) end
in loop 0 end
Поскольку тип изменен на
val walk : range list -> (real list -> unit) -> unit
Ваше использование также должно измениться на
fun do2D [y,x] = (* ... *) ()
fun do3D [z,y,x] = (* ... *) ()