গাণিতিক ব্যাখ্যা করা


9

একটি সামান্য পরিচিত তথ্য হ'ল আপনি যদি পর্যাপ্ত ভাষার এক্সটেনশানগুলি চালু করেন (জিএইচসি) হাস্কেল একটি গতিময় টাইপযুক্ত ব্যাখ্যা করা ভাষা হয়ে যায়! উদাহরণস্বরূপ নিম্নলিখিত প্রোগ্রামটি প্রয়োগ করে।

{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}

data Zero
data Succ a

class Add a b c | a b -> c
instance Add Zero a a
instance (Add a b c) => Add (Succ a) b (Succ c)

এটি আর হাস্কেলের মতো দেখায় না। একের পরিবর্তে অবজেক্টগুলির উপর অপারেটিংয়ের পরিবর্তে আমরা প্রকারভেদে অপারেট করি। প্রতিটি নম্বর এটি নিজস্ব টাইপ। ফাংশন পরিবর্তে আমাদের টাইপ ক্লাস আছে। ক্রিয়ামূলক নির্ভরতা আমাদের প্রকারের মধ্যে ফাংশন হিসাবে তাদের ব্যবহার করতে দেয়।

তাহলে আমরা কীভাবে আমাদের কোডটি চালাব? আমরা অন্য ক্লাস ব্যবহার করি

class Test a | -> a
 where test :: a
instance (Add (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)
  => Test a

এই সেট ধরণ testধরণ 4 + + 3. আমরা যদি এই ghci আমরা যে পাবেন মধ্যে খুলুন testটাইপ 7 প্রকৃতপক্ষে হল:

Ok, one module loaded.
*Main> :t test
test :: Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero))))))

কার্য

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

data Zero
data Succ a

এবং আপনার ক্লাসটি উপরের মতো একইভাবে মূল্যায়ন করা হবে। আপনার ক্লাসের নাম আপনি যা খুশি রাখতে পারেন।

আপনি যে কোনও জিএসিসি ল্যাঙ্গুয়েজ এক্সটেনশনগুলি ব্যবহার করতে পারেন কোনও বাইট ছাড়াই আপনার চান।

পরীক্ষার কেস

এই পরীক্ষার কেসগুলি অনুমান করে যে আপনার ক্লাসের নাম দেওয়া হয়েছে M, আপনি চাইলে অন্য কোনও নাম রাখতে পারেন।

class Test1 a| ->a where test1::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)=>Test1 a

class Test2 a| ->a where test2::a
instance (M Zero (Succ (Succ Zero)) a)=>Test2 a

class Test3 a| ->a where test3::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ Zero) a)=>Test3 a

class Test4 a| ->a where test4::a
instance (M (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))) (Succ (Succ (Succ Zero))) a)=>Test4 a

ফলাফল

*Main> :t test1
test1
  :: Succ
       (Succ
          (Succ
             (Succ
                (Succ (Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))
*Main> :t test2
test2 :: Zero
*Main> :t test3
test3 :: Succ (Succ (Succ (Succ Zero)))
*Main> :t test4
test4
  :: Succ
       (Succ
          (Succ
             (Succ
                (Succ
                   (Succ
                      (Succ
                         (Succ
                            (Succ
                               (Succ
                                  (Succ
                                     (Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))))))))

প্রযুক্তিগত সাক্ষাত্কার টাইপিং থেকে অনুপ্রেরণা আঁকুন


ভাষা এক্সটেনশন কি বিনামূল্যে? যদি তাই হয়?
আলু 44

@ আলু 44 ওহ হ্যাঁ সমস্ত ভাষার এক্সটেনশন বিনামূল্যে।
অ্যাডহক গার্ফ হান্টার

1
হেই ... এই পোস্টটি মেম-ই বলে মনে হচ্ছে যদিও তা না।
ম্যাজিক অক্টোপাস উরন

উত্তর:


9

130 121 বাইট

-9 বাইটস ধন্যবাদ অর্জান জোহানসেনকে

type family a+b where s a+b=a+s b;z+b=b
type family a*b where s a*b=a*b+b;z*b=z
class(a#b)c|a b->c
instance a*b~c=>(a#b)c

এটি অনলাইন চেষ্টা করুন!

এটি যোগ (+)এবং গুণনের জন্য বদ্ধ ধরণের পরিবারগুলি সংজ্ঞায়িত করে (*)। তারপরে একটি প্রকার শ্রেণিটি (#)সংজ্ঞায়িত করা হয় যা (*)টাইপ পরিবারকে টাইপক্লাস প্রলোগের দুনিয়াতে টাইপ ফ্যামিলির বিশ্ব থেকে রূপান্তর করতে একটি সমতা সীমাবদ্ধতার সাথে ব্যবহার করে ।


3
আপনি যদি সমীকরণগুলি অদলবদল করেন তবে আপনি এটি Zeroদ্বারা প্রতিস্থাপন করতে পারেন z
janর্জন জোহানসেন

1
@ Janর্জনজাহানসেন হয়ে গেছে। আমি কারও জন্য 9 বাইট সঞ্চয় করি এবং আমার জন্য 9 বাইট সংরক্ষণ করা হয়।
আলু 44

আমি টাইপ পরিবার ব্যবহার করতে জানেন না, কিন্তু হয়তো মত একটি ফাংশন এই যাতে আপনি নির্ধারণ করতে প্রয়োজন হবে না +দরকারী?
লিন

@ লিন যে শেষ পর্যন্ত আসে। টিআইও
আলু 44

1
@ হুইট উইজার্ড আমি ঠিক বুঝতে পেরেছি যে আমি মন্তব্যটিতে পোস্ট করা কোডটি কারণ এটি দীর্ঘ সময় এসেছে তা মূলত আপনার উত্তরটির লেজ পুনরাবৃত্ত সংস্করণ।
আলু 44

6

139 বাইট

class(a+b)c|a b->c;instance(Zero+a)a;instance(a+b)c=>(s a+b)(s c)
class(a*b)c|a b->c;instance(Zero*a)Zero;instance((a*b)c,(b+c)d)=>(s a*b)d

এটি অনলাইন চেষ্টা করুন!

একটি প্রকার অপারেটর সংজ্ঞায়িত করে *। প্রোলোগ প্রোগ্রামের সমতুল্য:

plus(0, A, A).
plus(s(A), B, s(C)) :- plus(A, B, C).
mult(0, _, 0).
mult(s(A), B, D) :- mult(A, B, C), plus(B, C, D).

আলু 44 এবং হাট উইজার্ড প্রতি 9 টি বাইট সংরক্ষণ করেছে। ধন্যবাদ!


আপনার বাইট মোটে আপনার ডেটা ঘোষণার গণনা করার দরকার নেই। আমি যখন সুযোগ পাব তখন এই প্রশ্নটি আরও পরিষ্কার করব
অ্যাড হক গার্ফ হান্টার

এছাড়াও আমি মনে করি আপনি এর fপরিবর্তে একটি জেনারেল ব্যবহার করতে পারেন Succ
অ্যাডহক গার্ফ হান্টার

1
আপনি কলোন খনন করে 9 বাইট সংরক্ষণ করতে পারেন।
আলু 44

আমি মনে করি হাট উইজার্ড 6 টি নয়, 9 টি সংরক্ষণ করেছে Suc
আলু 44

1

পারিবারিক সংস্করণ, 115 বাইট

type family(a%b)c where(a%b)(s c)=s((a%b)c);(s a%b)z=(a%b)b;(z%b)z=z
class(a#b)c|a b->c
instance(a%b)Zero~c=>(a#b)c

এটি অনলাইন চেষ্টা করুন!

এটি আলু 44 এর মতো একটি বদ্ধ ধরণের পরিবার ব্যবহার করে । অন্যান্য উত্তরের পরিবর্তে আমি কেবল 1 ধরণের পরিবার ব্যবহার করি।

type family(a%b)c where
  -- If the accumulator is Succ c:
  -- the answer is Succ of the answer if the accumulator were c
  (a%b)(s c)=s((a%b)c)
  -- If the left hand argument is Succ a, and the right hand is b
  -- the result is the result if the left were a and the accumulator were b
  (s a%b)z=(a%b)b
  -- If the left hand argument is zero
  -- the result is zero
  (z%b)z=z

এটি তিন ধরণের একটি অপারেটরকে সংজ্ঞায়িত করে। এটি মূলত প্রয়োগ করে (a*b)+c। যখনই আমরা সামগ্রীতে আমাদের ডান হাত যুক্তি যুক্ত করতে চাই আমরা তার পরিবর্তে এটি সঞ্চয়ের মধ্যে রাখি।

এটি আমাদের মোটেও সংজ্ঞায়িত (+)করার প্রয়োজন থেকে বাধা দেয় । প্রযুক্তিগতভাবে আপনি এই পরিবারটি ব্যবহার করে সংযোজন প্রয়োগ করতে পারেন

class Add a b c | a b -> c
instance (Succ Zero % a) b ~ c => Add a b c

ক্লাস-সংস্করণ, 137 বাইট

class(a#b)c d|a b c->d
instance(a#b)c d=>(a#b)(f c)(f d)
instance(a#b)b d=>(f a#b)Zero d
instance(Zero#a)Zero Zero
type(a*b)c=(a#b)Zero c

এটি অনলাইন চেষ্টা করুন!

এই শ্রেণীর সংস্করণটি পারিবারিক সংস্করণে কিছুটা ক্ষেত্র হারায়, তবে এটি এখানে স্বল্পতম শ্রেণীর সংস্করণের চেয়েও ছোট। এটি আমার পারিবারিক সংস্করণের মতোই ব্যবহার করে uses


ভাল লাগল, আমি দেখতে পাচ্ছি যে আপনার টাইপ পরিবার গাণিতিকভাবে একটি * বি + সি প্রয়োগ করছে। "বিভাগ" এর উল্লেখটি কি "সংযোজন" বোঝানো হয়েছে?
আলু 44

বিটিডব্লিউ, আপনি এই মুহুর্তে আপনার নিজের বিশেষ লঙ্ঘন করছেন be "এমন একটি শ্রেণি প্রয়োগ করুন যা দুটি পেনো সংখ্যাকে গুণ করে" আপনার বর্তমানে যা আছে তা কোনও শ্রেণি নয়, তবে তা উদয় হওয়া হবে Constraint। সুতরাং আপনার হয় হয় স্পেক আপডেট করুন অথবা ফর্মটি ফিরে আসা উচিত যা কোনও প্রকার প্রতিশব্দের পরিবর্তে ক্লাস ব্যবহার করে। আমি যদি প্রতিশব্দ টাইপটি ব্যবহার করতে পারি তবে আমি আমার উত্তরটি 96 বাইটে নামতে পারতাম, সুতরাং এটি আপনার চেয়ে আমাকে আরও একটি বাইট সংরক্ষণ করে
আলু 44

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