هل تقوم بالمشي بأبعاد N في تعلم الآلة الوظيفي البحت؟
-
20-08-2019 - |
سؤال
والفكرة هي السير على أبعاد متعددة، كل واحد منها يعرف بأنه نطاق
(* lower_bound, upper_bound, number_of_steps *)
type range = real * real * int
وظائف مثل ذلك fun foo y x
أو fun foo z y x
يمكن تطبيقها على المربع X بأكملهY أو المكعب Xص * ض.
SML/NJ لا يحب تنفيذي أدناه:
test2.sml:7.5-22.6 Error: right-hand-side of clause doesn't agree with function result type [circularity]
expression: (real -> 'Z) -> unit
result type: 'Z -> 'Y
in declaration:
walk = (fn arg => (fn <pat> => <exp>))
إليك الرمز:
fun walk [] _ = ()
| walk (r::rs) f =
let
val (k0, k1, n) = r
val delta = k1 - k0
val step = delta / real n
fun loop 0 _ = ()
| loop i k =
let in
walk rs (f k) ; (* Note (f k) "eats" the first argument.
I guess SML doesn't like having the
type of walk change in the middle of its
definition *)
loop (i - 1) (k + step)
end
in
loop n k0
end
fun do2D y x = (* ... *) ()
fun do3D z y x = (* ... *) ()
val x_axis = (0.0, 1.0, 10)
val y_axis = (0.0, 1.0, 10)
val z_axis = (0.0, 1.0, 10)
val _ = walk [y_axis, x_axis] do2D
val _ = walk [z_axis, y_axis, x_axis] do3D
هل هذا النوع من البناء ممكن حتى؟
ورحب بأي مؤشر.
المحلول
يكون walk
يمكن التعبير عنها في نظام نوع ML؟
val walk : range list -> (real -> real -> unit) -> unit
val walk : range list -> (real -> real -> real -> unit) -> unit
لا يمكن أن توجد نفس القيمة مع كلا النوعين في تعلم الآلة.
ومع ذلك، يمكننا بسهولة إنشاء قيم لكل نوع من الأنواع المطلوبة.
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] = (* ... *) ()
نصائح أخرى
fun walk lst f = let
fun aux rev_prefix [] = f (rev rev_prefix)
| aux rev_prefix (r::rs) = let
val (k0, k1, n) = r
val delta = k1 - k0
val step = delta / real n
fun loop 0 _ = ()
| loop i k = (
aux (k+step :: rev_prefix) rs;
loop (i - 1) (k + step)
)
in
loop n k0
end
in
aux [] lst
end
fun do2D [x,y] = print (Real.toString x ^ "\t" ^
Real.toString y ^ "\n")
fun do3D [x,y,z] = print (Real.toString x ^ "\t" ^
Real.toString y ^ "\t" ^
Real.toString z ^ "\n")
val x_axis = (0.0, 1.0, 10)
val y_axis = (0.0, 1.0, 10)
val z_axis = (0.0, 1.0, 10)
val () = walk [y_axis, x_axis] do2D
val () = walk [z_axis, y_axis, x_axis] do3D
وجدت هذا تنفيذ لعدد متغير من الحجج.لست متأكدًا من تطبيقه ولكنه يبدو قبيحًا جدًا.
لا تنتمي إلى StackOverflow