এসএমএল ডেটাটাইপগুলির সাবসেট হিসাবে সাব টাইপস


10

নিখুঁতভাবে কার্যকরী ডেটা স্ট্রাকচার সম্পর্কিত ওকাসাকির বইটি সম্পর্কে আমি যে কয়েকটি বিষয় অপছন্দ করি সেগুলির একটি হ'ল তার কোডটি অক্ষয় বিন্যাসের সাথে মেশানো থাকে। উদাহরণ হিসাবে, আমি তার বাস্তব-সময় সারিগুলি প্রয়োগ করব (অপ্রয়োজনীয় স্থগিতাদেশগুলি অপসারণের জন্য রিফ্যাক্টার্ড):

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

তবে আমি পূর্ণ-বিকাশশীল নির্ভরশীল প্রকারগুলি, বা এমনকি জিএডিডি, বা নির্দিষ্ট প্রোগ্রামারদের ব্যবহার করা অন্য কোনও ক্রেজি জিনিস চাই না। আমি কেবল বিদ্যমান এমএল প্রকারের ইনডাকটিভলি সংজ্ঞায়িত সাবসেটগুলি "উত্সাহিত" করে সাব টাইপগুলি সংজ্ঞায়িত করতে চাই। এটা কি সম্ভব?

উত্তর:


20

এই ধরণের প্রকারের - যেখানে আপনি গ্রহণযোগ্য মানের একটি ব্যাকরণ দিয়ে একটি উপপ্রকার (মূলত) সংজ্ঞায়িত করেন - তাকে ডেটাসোর্ট সংশোধন বলে

  • তারা ১৯৯১ সালে পিএলডিআই পেপারে, এমএল-এর জন্য পরিশোধিত প্রকারের টিম ফ্রিম্যান এবং ফ্র্যাঙ্ক পেফেনিংয়ের মাধ্যমে প্রবর্তিত হয়েছিল ।

  • রোয়ান ডেভিস তাঁর পিএইচডি থিসিস, প্রাকটিকাল রিফাইনমেন্ট টাইপ চেকিংয়ে রিফাইনামেন্ট টাইপের জন্য টাইপ অনুক্রমের অধ্যয়ন করেছিলেন । তিনি এটি এসএমএলের এক্সটেনশন হিসাবে প্রয়োগ করেছিলেন, তবে অনলাইনে এটি উপলব্ধ কিনা তা আমার জানা নেই।

  • জোশুয়া ডানফিল্ড তাঁর থিসিসে টাইপ রিফাইনমেন্টগুলির একটি ইউনিফাইড সিস্টেমের মধ্যে ফ্যানসিয়ার লাইটওয়েট টাইপের নির্ভরতার সাথে কীভাবে ডেটাসোর্ট সংশোধনগুলি একত্রিত করবেন তা অধ্যয়ন করেছিলেন । তিনি এটি তার স্টারডাস্ট ভাষায়ও প্রয়োগ করেছেন , যা অনলাইনে পাওয়া যায়:

    http://www.mpi-sws.org/~joshua/stardust/


3
রোয়ান ডেভিস বাস্তবায়ন এখানে উপলব্ধ: github.com/rowandavies/sML-cidre
নোয়াম জিলবার্গার

1

আমি জিএডিডি, টাইপফ্যামিলি, ডেটাপাইন্ডস এবং টাইপঅ্যাপেটর (কেবল নান্দনিকতার জন্য) ব্যবহার করতে পারি এবং আপনার পরে যা তৈরি করতে পারি তা তৈরি করতে পারি:

data Term0 varb lamb letb where
    Lam :: lamb -> Term0 varb lamb letb -> Term0 varb lamb letb
    Let :: letb -> Term0 varb lamb letb -> Term0 varb lamb letb -> Term0 varb lamb letb
    Var :: varb -> Term0 varb lamb letb
    App :: Term0 varb lamb letb -> Term0 varb lamb letb -> Term0 varb lamb letb

type Term b = Term0 b b b

data Terms = Lets | Lams | Vars

type family  t /// (ty :: Terms) where
    Term0 a b c /// Vars = Term0 Void b c
    Term0 a b c /// Lams = Term0 a Void c
    Term0 a b c /// Lets = Term0 a b Void

Now, I can write functions with more refined types:

unlet :: Term b -> Term b /// Lets

আপনার উত্তরের জন্য ধন্যবাদ. আমি জিএইচসি এর TypeFamiliesসম্পূর্ণভাবে নীতিগত ভিত্তিতে অপছন্দ করি : এটি প্যারামিট্রিকটি এবং বিনামূল্যে উপপাদ্যগুলি ধ্বংস করে। আমিও GADTs সাথেও আরামদায়ক নই, কারণ একটি GADT দেওয়া Foo a, দুই isomorphic ধরনের থাকতে পারে Barএবং Qux, যেমন যে Foo Barএবং Foo Quxisomorphic নয়। এটি গাণিতিক অন্তর্নিহিতের বিরোধিতা করে যা মানচিত্রের সমান সমান হয় - এবং, স্তরের স্তরে আইসোমর্ফিিজমই সাম্যের সঠিক ধারণা।
পাইয়ান

আমি আপনার যোগ্যতা বুঝতে পারি, তবে এটি বিশেষায়িত সাধারণীকরণের অনুমতি দেয়, যা অনুশীলনে আমি বেশ মূল্যবান বলে মনে করি।
স্যামুয়েল শ্লেসিংগার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.