নির্ভরশীল পদ্ধতি ধরণের জন্য কিছু বাধ্যমূলক ব্যবহারের মামলাগুলি কী কী?


127

নির্ভরশীল পদ্ধতি ধরণের, যা আগে পরীক্ষামূলক বৈশিষ্ট্য হিসাবে ব্যবহৃত হত এখন ট্রাঙ্কে ডিফল্টরূপে সক্ষম হয়েছে এবং স্পষ্টতই এটি স্কেলা সম্প্রদায়ের মধ্যে কিছুটা উত্তেজনা তৈরি করেছে বলে মনে হয় ।

প্রথম নজরে, এটি কী জন্য কার্যকর হতে পারে তা অবিলম্বে সুস্পষ্ট নয়। হাইকো সিবার্গার নির্ভরশীল পদ্ধতির ধরণের একটি সাধারণ উদাহরণ এখানে পোস্ট করেছেন , যা মন্তব্যটিতে দেখা যায় যে পদ্ধতিগুলির ক্ষেত্রে টাইপ পরামিতিগুলির সাথে সহজেই পুনরুত্পাদন করা যেতে পারে। সুতরাং এটি খুব জোরালো উদাহরণ ছিল না। (আমি সম্ভবত কিছু স্পষ্টরূপে অনুপস্থিত। দয়া করে যদি আমাকে ঠিক করে দিন।)

নির্ভরযোগ্য পদ্ধতির ধরণের ক্ষেত্রে তারা ব্যবহারের ক্ষেত্রে কার্যকরভাবে কার্যকর এবং কার্যকর উদাহরণগুলি কী কী যেখানে তারা বিকল্পগুলির চেয়ে স্পষ্টভাবে সুবিধাজনক?

তাদের সাথে আমরা কী আকর্ষণীয় জিনিসগুলি করতে পারি যা আগে সম্ভব / সহজ ছিল না?

বিদ্যমান টাইপ সিস্টেম বৈশিষ্ট্যগুলির চেয়ে তারা আমাদের কী কিনে?

এছাড়াও, নির্ভরশীল পদ্ধতির ধরনগুলি কি অন্যান্য উন্নত টাইপ করা ভাষার যেমন হ্যাস্কেল, ওসিএএমএল এর টাইপ সিস্টেমে পাওয়া কোন বৈশিষ্ট্য থেকে অনুপ্রেরণা তৈরি করে বা আঁকতে পারে?


আপনার আগ্রহী হতে পারে হাস্কেল.আর.
ড্যান বার্টন

লিঙ্কের জন্য ধন্যবাদ, ড্যান! আমি সাধারণভাবে নির্ভরশীল প্রকার সম্পর্কে সচেতন, তবে নির্ভরশীল পদ্ধতির ধরণের ধারণাটি আমার কাছে তুলনামূলকভাবে নতুন।
অনুপস্থিত

আমার কাছে মনে হয় "নির্ভরশীল পদ্ধতি প্রকারগুলি" হ'ল প্রকারগুলি যা কোনও পদ্ধতির ইনপুট ধরণের (একাধিক পদ্ধতির উপর নির্ভর করে) যে পদ্ধতিতে পদক্ষেপটি প্রেরণ করা হয় তা সহ); নির্ভরশীল ধরণের সাধারণ ধারণার বাইরে পাগল কিছুই নেই। সম্ভবত আমি কিছু মিস করছি?
ড্যান বার্টন

না, আপনি করেন নি, তবে দৃশ্যত আমি তা করেছিলাম। :-) আমি দুজনের মধ্যে লিঙ্কটি আগে দেখিনি। এটি এখন স্ফটিক পরিষ্কার।
মিসিংফ্যাক্টর

উত্তর:


112

কম বেশি সদস্যের (যেমন নেস্টেড) প্রকারের ব্যবহার নির্ভরশীল পদ্ধতি ধরণের প্রয়োজনের জন্ম দিতে পারে। বিশেষত, আমি বজায় রেখেছি যে নির্ভরশীল পদ্ধতি ছাড়াই ক্লাসিক কেকের ধরণটি অ্যান্টি-প্যাটার্ন হওয়ার কাছাকাছি রয়েছে।

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

আমি আমার এডভান্সড স্কাল প্রশিক্ষণ কোর্স চলাকালীন একটি অনুশীলন দিয়ে চিত্রিত করব ,

trait ResourceManager {
  type Resource <: BasicResource
  trait BasicResource {
    def hash : String
    def duplicates(r : Resource) : Boolean
  }
  def create : Resource

  // Test methods: exercise is to move them outside ResourceManager
  def testHash(r : Resource) = assert(r.hash == "9e47088d")  
  def testDuplicates(r : Resource) = assert(r.duplicates(r))
}

trait FileManager extends ResourceManager {
  type Resource <: File
  trait File extends BasicResource {
    def local : Boolean
  }
  override def create : Resource
}

class NetworkFileManager extends FileManager {
  type Resource = RemoteFile
  class RemoteFile extends File {
    def local = false
    def hash = "9e47088d"
    def duplicates(r : Resource) = (local == r.local) && (hash == r.hash)
  }
  override def create : Resource = new RemoteFile
}

এটা তোলে সর্বোত্তম পিষ্টক প্যাটার্ন একটি উদাহরণ: আমরা বিমূর্ত যা ক্রমশ অনুক্রমের মাধ্যমে পরিশ্রুত করা হয় একটি পরিবার আছে ( ResourceManager/ Resourceদ্বারা পরিশ্রুত করা হয় FileManager/ Fileযার দ্বারা পরিশ্রুত ঘুরে হয় NetworkFileManager/ RemoteFile)। এটি খেলনার উদাহরণ, তবে প্যাটার্নটি আসল: এটি স্কালার সংকলক জুড়ে ব্যবহৃত হয় এবং স্কালা ইক্লিপ্স প্লাগইনে ব্যাপকভাবে ব্যবহৃত হয়েছিল।

এখানে ব্যবহার বিমূর্তির উদাহরণ,

val nfm = new NetworkFileManager
val rf : nfm.Resource = nfm.create
nfm.testHash(rf)
nfm.testDuplicates(rf)

নোট করুন যে পাথ নির্ভরতার অর্থ সংকলকটি গ্যারান্টি দিবে যে এতে testHashএবং testDuplicatesপদ্ধতিগুলি NetworkFileManagerকেবলমাত্র তার সাথে সম্পর্কিত আর্গুমেন্টের সাথে ডাকা যাবে। এটি নিজস্ব RemoteFiles, আর কিছুই নয়।

এটি অনস্বীকার্যভাবে একটি আকাঙ্ক্ষিত সম্পত্তি, তবে মনে করুন আমরা এই পরীক্ষার কোডটিকে অন্য উত্স ফাইলে স্থানান্তরিত করতে চেয়েছিলাম? নির্ভরশীল পদ্ধতির ধরণের সাথে ResourceManagerশ্রেণিবদ্ধের বাইরে এই পদ্ধতিগুলি পুনরায় সংজ্ঞায়িত করা তুচ্ছভাবে সহজ ,

def testHash4(rm : ResourceManager)(r : rm.Resource) = 
  assert(r.hash == "9e47088d")

def testDuplicates4(rm : ResourceManager)(r : rm.Resource) = 
  assert(r.duplicates(r))

নির্ভরশীল পদ্ধতির ধরণের ব্যবহারগুলি এখানে নোট করুন: দ্বিতীয় আর্গুমেন্টের ধরণ ( rm.Resource) প্রথম যুক্তি ( rm) এর মানের উপর নির্ভর করে ।

নির্ভরশীল পদ্ধতির ধরণ ছাড়াই এটি করা সম্ভব, তবে এটি অত্যন্ত বিশ্রী এবং প্রক্রিয়াটি বেশ অদম্য: আমি প্রায় দুই বছর ধরে এই কোর্সটি শিখিয়ে চলেছি, এবং সেই সময়ে, কোনওরই নিরবচ্ছিন্ন একটি কার্যকর সমাধান নিয়ে এসেছিল।

এটি নিজের জন্য চেষ্টা করুন ...

// Reimplement the testHash and testDuplicates methods outside
// the ResourceManager hierarchy without using dependent method types
def testHash        // TODO ... 
def testDuplicates  // TODO ...

testHash(rf)
testDuplicates(rf)

কিছুক্ষণ লড়াই করার পরে আপনি সম্ভবত আবিষ্কার করবেন যে আমি (বা সম্ভবত এটি ডেভিড ম্যাকআইভার ছিল, আমাদের মধ্যে কোনটি শব্দটি রচিত হয়েছিল তা আমরা মনে করতে পারি না) এটিকে ডুমের বেকারি বলে।

সম্পাদনা: sensক্যমত্য হ'ল ডুমার ম্যাকআইভারের মুদ্রা ছিল ডুমের বেকারি ...

বোনাসের জন্য: স্কালার সাধারণভাবে নির্ভরশীল ধরণের রূপ (এবং এর অংশ হিসাবে নির্ভরশীল ধরণের প্রকারগুলি) প্রোগ্রামিং ভাষা বিটা দ্বারা অনুপ্রাণিত হয়েছিল ... এগুলি স্বাভাবিকভাবেই বিটার ধারাবাহিক বাসা বাঁধার শব্দ থেকে উদ্ভূত হয়েছিল। আমি এই রূপটিতে নির্ভরশীল প্রকারের এমন কোনও নির্লজ্জ মূলধারার প্রোগ্রামিং ভাষা জানি না know কক, কেয়েন, এপিগ্রাম এবং আগদার মতো ভাষার নির্ভরশীল টাইপিংয়ের আলাদা রূপ রয়েছে যা কিছু দিক থেকে আরও সাধারণ, তবে এটি টাইপ সিস্টেমের অংশ হয়ে উল্লেখযোগ্যভাবে পৃথক হয় যা স্কালার বিপরীতে সাব টাইপিংয়ের মতো নয়।


2
ডেভিড ম্যাকআইভারই এই শব্দটি তৈরি করেছিলেন, তবে যে কোনও ক্ষেত্রে এটি বেশ বর্ণনামূলক। নির্ভরশীল পদ্ধতির ধরনগুলি কেন এত উত্তেজনাপূর্ণ তা এটি একটি চমত্কার ব্যাখ্যা। চমৎকার কাজ!
ড্যানিয়েল স্পিউয়াক

বেশ কিছুদিন আগে এটি আমাদের দুজনের মধ্যে # স্ক্যালায় কথোপকথনে প্রাথমিকভাবে উঠে এসেছিল ... যেমন আমি বলেছিলাম যে আমাদের মধ্যে কে এটি আগে বলেছিল তা আমি মনে করতে পারি না।
মাইলস সাবিন

দেখে মনে হচ্ছে আমার স্মৃতিটি আমার উপর কৌশল অবলম্বন করছে ... sensকমত্য হল এটি ডেভিড ম্যাকআইভারের মুদ্রা।
মাইলস সাবিন

হ্যাঁ, আমি তখন সেখানে (# স্ক্যালায়) ছিলাম না, তবে জর্জি ছিল এবং সেখানেই আমি আমার তথ্য পেয়ে যাচ্ছিলাম।
ড্যানিয়েল স্পিওক

অ্যাবস্ট্রাক্ট টাইপের সদস্য সংশোধন ব্যবহার করে আমি টেস্টহ্যাশ 4 ফাংশনটি মোটামুটি বেদাহীনভাবে প্রয়োগ করতে সক্ষম হয়েছি। def testHash4[R <: ResourceManager#BasicResource](rm: ResourceManager { type Resource = R }, r: R) = assert(r.hash == "9e47088d")আমি মনে করি এটি নির্ভরশীল ধরণের অন্য রূপ হিসাবে বিবেচনা করা যেতে পারে।
মার্কো ভ্যান হিলস্ট

53
trait Graph {
  type Node
  type Edge
  def end1(e: Edge): Node
  def end2(e: Edge): Node
  def nodes: Set[Node]
  def edges: Set[Edge]
}

অন্য কোথাও আমরা স্থিরভাবে গ্যারান্টি দিতে পারি যে আমরা দুটি পৃথক গ্রাফ থেকে নোড মিশ্রিত করছি না, যেমন:

def shortestPath(g: Graph)(n1: g.Node, n2: g.Node) = ... 

অবশ্যই, এটি ইতিমধ্যে ভিতরে সংজ্ঞায়িত হয়ে কাজ করেছে Graph, তবে বলুন আমরা এটি সংশোধন করতে পারি না Graphএবং এর জন্য একটি "পিম্প আমার লাইব্রেরি" এক্সটেনশন লিখছি।

দ্বিতীয় প্রশ্ন সম্পর্কে: এই বৈশিষ্ট্যটি দ্বারা সক্ষম করা প্রকারগুলি সম্পূর্ণ নির্ভরশীল ধরণের চেয়ে অনেক বেশি দুর্বল (এর স্বাদের জন্য আগডায় নির্ভরশীল টাইপড প্রোগ্রামিং দেখুন )) আমি মনে করি না এর আগে আমি কোনও উপমা দেখেছি।


6

প্রকারের পরামিতিগুলির পরিবর্তে কংক্রিট বিমূর্ত প্রকারের সদস্য ব্যবহার করা হলে এই নতুন বৈশিষ্ট্যটি প্রয়োজন । যখন টাইপ প্যারামিটারগুলি ব্যবহৃত হয়, নীচের সরলীকৃত উদাহরণ হিসাবে পারিবারিক পলিমারফিজম ধরণের নির্ভরতা স্কালার সর্বশেষ এবং কিছু পুরানো সংস্করণে প্রকাশ করা যেতে পারে।

trait C[A]
def f[M](a: C[M], b: M) = b
class C1 extends C[Int]
class C2 extends C[String]

f(new C1, 0)
res0: Int = 0
f(new C2, "")
res1: java.lang.String = 
f(new C1, "")
error: type mismatch;
 found   : C1
 required: C[Any]
       f(new C1, "")
         ^

এটি সম্পর্কিত নয়। ধরণের সদস্যদের সাথে আপনি একই ফলাফলের জন্য পরিমার্জনগুলি ব্যবহার করতে পারেন: trait C {type A}; def f[M](a: C { type A = M}, b: M) = 0;class CI extends C{type A=Int};class CS extends C{type A=String}ইত্যাদি
এনএফজিজি

যে কোনও ক্ষেত্রে নির্ভরশীল পদ্ধতির ধরণের সাথে এর কোনও সম্পর্ক নেই। উদাহরণস্বরূপ অ্যালেক্সির উদাহরণটি ধরুন ( স্ট্যাকওভারফ্লো . com / a / 7860821 / 333643 )। আপনার পদ্ধতির ব্যবহার (আমি মন্তব্য করা সংশোধন সংস্করণ সহ) ব্যবহার করে লক্ষ্য অর্জন করতে পারে না। এটি নিশ্চিত করবে যে n1.Node =: = n2.Node, তবে এটি উভয়টি একই গ্রাফে রয়েছে তা নিশ্চিত করবে না। আইআইইউসি ডিএমটি এটি নিশ্চিত করে।
এনএফজি

@nafg এটি নির্দেশ করার জন্য ধন্যবাদ। আমি কংক্রিট শব্দটি যুক্ত করেছি যাতে এটি পরিষ্কার হয় যে আমি টাইপ সদস্যদের জন্য পরিশোধন ক্ষেত্রে উল্লেখ করছি না। আমি যতদূর দেখতে পাচ্ছি, এটি এখনও আপনার নির্ভরযোগ্য পদ্ধতি (যা সম্পর্কে আমি অবগত ছিলাম) তবুও নির্ভরশীল পদ্ধতির ধরণের ক্ষেত্রে এটি বৈধ ব্যবহারের ক্ষেত্রে যে অন্যান্য ব্যবহারের ক্ষেত্রে তাদের আরও ক্ষমতা থাকতে পারে is নাকি আমি আপনার দ্বিতীয় মন্তব্যের মৌলিক সারটি মিস করেছি?
শেলবি মুর তৃতীয়

3

আমি পরিবেশগত অবস্থার সাথে একধরণের ঘোষণামূলক প্রোগ্রামিংয়ের ইন্টারপোশনের জন্য একটি মডেল বিকাশ করছি । বিশদগুলি এখানে প্রাসঙ্গিক নয় (উদাহরণস্বরূপ কলব্যাকগুলি সম্পর্কে বিশদ এবং সিরিয়ালাইজারের সাথে মিলিত অভিনেতা মডেলের ধারণাগত মিল)।

প্রাসঙ্গিক সমস্যাটি হল রাষ্ট্রীয় মানগুলি হ্যাশ মানচিত্রে সংরক্ষণ করা হয় এবং হ্যাশ কী মান দ্বারা রেফারেন্স করা হয়। ক্রিয়াকলাপগুলি পরিবেশ থেকে মূল্যবোধগুলি পরিবর্তনযোগ্য যুক্তিগুলি ইনপুট করে, এ জাতীয় অন্যান্য ক্রিয়াকলাপ কল করতে পারে এবং পরিবেশকে রাষ্ট্র লিখতে পারে। তবে ফাংশনগুলিকে পরিবেশ থেকে মানগুলি পড়ার অনুমতি নেই (সুতরাং ফাংশনটির অভ্যন্তরীণ কোড রাষ্ট্র পরিবর্তনের ক্রমের উপর নির্ভর করে না এবং এইভাবে সেই অর্থে ঘোষিত থাকে)। স্কালায় এটি কীভাবে টাইপ করবেন?

এনভায়রনমেন্ট ক্লাসে অবশ্যই একটি ওভারলোডেড পদ্ধতি থাকতে হবে যা কল করতে এই জাতীয় ফাংশনকে ইনপুট করে এবং ফাংশনের আর্গুমেন্টের হ্যাশ কীগুলি ইনপুট করে। সুতরাং এই পদ্ধতিটি হ্যাশ মানচিত্র থেকে প্রয়োজনীয় মানগুলির সাথে ফাংশনটিকে কল করতে পারে, মানগুলিতে পাবলিক রিড অ্যাক্সেস সরবরাহ না করে (এইভাবে প্রয়োজন হিসাবে, পরিবেশ থেকে মূল্যবোধগুলি পড়ার ক্ষমতাকে অস্বীকার করে)।

অতএব, যদি এরা হ্যাশ কী স্ট্রিং বা পূর্ণসংখ্যা হ্যাশ মূল্যবোধ, হ্যাশ মানচিত্র উপাদান ধরনের স্ট্যাটিক টাইপিং হয় subsumes কোন বা AnyRef করার জন্য (হ্যাশ মানচিত্র কোড নিচে দেখানো হয়নি), এবং এইভাবে একটি রান-টাইম মেলেনি ঘটতে পারে, অর্থাত্ এটা সম্ভব হবে প্রদত্ত হ্যাশ কীটির জন্য হ্যাশ মানচিত্রে যে কোনও ধরণের মান রাখতে।

trait Env {
...
  def callit[A](func: Env => Any => A, arg1key: String): A
  def callit[A](func: Env => Any => Any => A, arg1key: String, arg2key: String): A
}

যদিও আমি নিম্নলিখিতটি পরীক্ষা করিনি, তাত্ত্বিকভাবে আমি রানটাইম নিয়োগের সময় ক্লাসের নামগুলি থেকে হ্যাশ কীগুলি পেতে পারি classOf, সুতরাং একটি হ্যাশ কীটি স্ট্রিংয়ের পরিবর্তে একটি শ্রেণীর নাম (কোনও শ্রেণীর নামে একটি স্ট্রিং এম্বেড করার জন্য স্কালার ব্যাকটিক্স ব্যবহার করে)।

trait DependentHashKey {
  type ValueType
}
trait `the hash key string` extends DependentHashKey {
  type ValueType <: SomeType
}

সুতরাং স্থিতিশীল ধরনের সুরক্ষা অর্জন করা হয়।

def callit[A](arg1key: DependentHashKey)(func: Env => arg1key.ValueType => A): A

যখন আমাদের একটি একক মানের মধ্যে আর্গুমেন্ট কীগুলি পাস করার দরকার হয়, তখন আমি পরীক্ষা করিনি, তবে ধরে নিন আমরা একটি টুপল ব্যবহার করতে পারি, উদাহরণস্বরূপ 2 টি আর্গুমেন্ট ওভারলোডের জন্য def callit[A](argkeys: Tuple[DependentHashKey,DependentHashKey])(func: Env => argkeys._0.ValueType => argkeys._1.ValueType => A): A। আমরা আর্গুমেন্ট কীগুলির সংগ্রহটি ব্যবহার করব না, কারণ উপাদানটির সংগ্রহের ধরণের উপাদানগুলির সংকলন (সংকলন-সময়ে অজানা) গ্রহণ করা হবে।
শেলবি মুর III

"হ্যাশ মানচিত্রের উপাদান স্ট্যাটিক টাইপিংয়ের যে কোনও বা যেকোনোআরএফ-তে সাবস্কিপশন" - আমি অনুসরণ করি না। আপনি যখন এলিমেন্ট টাইপ বলছেন তখন কী কী টাইপ বা মান টাইপ বলতে বোঝায় (অর্থাত হ্যাশম্যাপে প্রথম বা দ্বিতীয় ধরণের আর্গুমেন্ট)? এবং কেন এটি গ্রস্ত হবে?
রবিন গ্রিন

@ রবিনগ্রিন হ্যাশ টেবিলের মানগুলির ধরণ। আফায়ার, সাবমিট হয়েছে কারণ আপনি স্কেলায় একটি সংকলনে একাধিক প্রকারের রাখতে পারবেন না যদি না আপনি তাদের সাধারণ সুপারটাইপটি গ্রহন করেন, কারণ স্কালার কোনও ইউনিয়ন (বিভাজন) টাইপ নেই। স্কালায় সাবস্ক্রিপশন সম্পর্কে আমার প্রশ্নোত্তর দেখুন।
শেলবি মুর III
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.