নিখুঁতভাবে কার্যকরী ডেটা স্ট্রাকচার সম্পর্কিত ওকাসাকির বইটি সম্পর্কে আমি যে কয়েকটি বিষয় অপছন্দ করি সেগুলির একটি হ'ল তার কোডটি অক্ষয় বিন্যাসের সাথে মেশানো থাকে। উদাহরণ হিসাবে, আমি তার বাস্তব-সময় সারিগুলি প্রয়োগ করব (অপ্রয়োজনীয় স্থগিতাদেশগুলি অপসারণের জন্য রিফ্যাক্টার্ড):
infixr 5 :::
datatype 'a stream = Nil | ::: of 'a * 'a stream lazy
structure RealTimeQueue :> QUEUE =
struct
(* front stream, rear list, schedule stream *)
type 'a queue = 'a stream * 'a list * 'a stream
(* the front stream is one element shorter than the rear list *)
fun rotate (x ::: $xs, y :: ys, zs) = x ::: $rotate (xs, ys, y ::: $zs)
| rotate (Nil, y :: nil, zs) = y ::: $zs
fun exec (xs, ys, _ ::: $zs) = (xs, ys, zs)
| exec args = let val xs = rotate args in (xs, nil, xs) end
(* public operations *)
val empty = (Nil, nil, Nil)
fun snoc ((xs, ys, zs), y) = exec (xs, y :: ys, zs)
fun uncons (x ::: $xs, ys, zs) = SOME (x, exec (xs, ys, zs))
| uncons _ = NONE
end
যেমন দেখা যায় rotate
ততটা পরিসীমা ছাড়াই নয়, কারণ এটি পিছনের তালিকাটি খালি রয়েছে এমন ক্ষেত্রে এটি কাভার করে না। বেশিরভাগ স্ট্যান্ডার্ড এমএল বাস্তবায়ন এটি সম্পর্কে একটি সতর্কতা উত্পন্ন করবে। আমরা জানি যে পিছনের তালিকাটি সম্ভবত খালি থাকতে পারে না, কারণ rotate
পূর্ব শর্তটি হ'ল পিছনের তালিকাটি সামনের স্ট্রিমের চেয়ে একটি উপাদান দীর্ঘতর। তবে প্রকারের পরীক্ষক জানেন না - এবং এটি সম্ভবত জানতে পারে না, কারণ এই ঘটনাটি এমএল টাইপ সিস্টেমে অনুপযুক্ত।
এই মুহুর্তে, এই সতর্কতাটি দমন করার জন্য আমার সমাধানটি নিম্নলিখিত অযোগ্য হ্যাক:
fun rotate (x ::: $xs, y :: ys, zs) = x ::: $rotate (xs, ys, y ::: $zs)
| rotate (_, ys, zs) = foldl (fn (x, xs) => x ::: $xs) zs ys
তবে আমি যা চাই তা হ'ল একটি টাইপ সিস্টেম যা বুঝতে পারে যে প্রতিটি ত্রিপলিটি বৈধ যুক্তি নয় rotate
। আমি টাইপ সিস্টেমটি আমাকে এর মতো ধরণের সংজ্ঞা দিতে দেয়:
type 'a triplet = 'a stream * 'a list * 'a stream
subtype 'a queue of 'a triplet
= (Nil, nil, Nil)
| (xs, ys, zs) : 'a queue => (_ ::: $xs, _ :: ys, zs)
| (xs, ys, zs) : 'a queue => (_ ::: $xs, ys, _ ::: $zs)
এবং তারপরে অনুমান:
subtype 'a rotatable of 'a triplet
= (xs, ys, _) : 'a rotatable => (_ ::: $xs, _ :: ys, _)
| (Nil, y :: nil, _)
subtype 'a executable of 'a triplet
= (xs, ys, zs) : 'a queue => (xs, ys, _ ::: $zs)
| (xs, ys, Nil) : 'a rotatable => (xs, ys, Nil)
val rotate : 'a rotatable -> 'a stream
val exec : 'a executable -> 'a queue
তবে আমি পূর্ণ-বিকাশশীল নির্ভরশীল প্রকারগুলি, বা এমনকি জিএডিডি, বা নির্দিষ্ট প্রোগ্রামারদের ব্যবহার করা অন্য কোনও ক্রেজি জিনিস চাই না। আমি কেবল বিদ্যমান এমএল প্রকারের ইনডাকটিভলি সংজ্ঞায়িত সাবসেটগুলি "উত্সাহিত" করে সাব টাইপগুলি সংজ্ঞায়িত করতে চাই। এটা কি সম্ভব?