سؤال

والفكرة هي السير على أبعاد متعددة، كل واحد منها يعرف بأنه نطاق

(* 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

وجدت هذا تنفيذ لعدد متغير من الحجج.لست متأكدًا من تطبيقه ولكنه يبدو قبيحًا جدًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top