আমি কীভাবে স্থির ব্যবহার করব এবং এটি কীভাবে কাজ করবে?


88

আমি ডকুমেন্টেশন দ্বারা কিছুটা বিভ্রান্ত হয়ে fixপড়েছিলাম (যদিও আমি মনে করি এটি এখন কী করা উচিত তা আমি বুঝতে পেরেছি), তাই আমি উত্স কোডটির দিকে তাকালাম। এটি আমাকে আরও বিভ্রান্ত করেছে:

fix :: (a -> a) -> a
fix f = let x = f x in x

এই ঠিক কিভাবে একটি নির্দিষ্ট পয়েন্ট ফিরে আসে?

আমি কমান্ড লাইনে চেষ্টা করে দেখার সিদ্ধান্ত নিয়েছি:

Prelude Data.Function> fix id
...

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


69
স্পষ্ট উত্তরটি হ'ল " fix errorফিক্সটির কোনও বাস্তব ব্যবহার নেই, এটি ঠিক সেখানে রয়েছে যাতে আপনি গিগি টাইপ করতে পারেন এবং নিজের সম্পর্কে ভাল বোধ করতে পারেন ।"
টমাস এম ডুবুইসন

4
@ টমএমডি - মজার আমি মনে রাখব যে যদি কেউ আমাকে জিজ্ঞাসা করে তবে কী ঠিক করে এবং আমি প্রচণ্ড অনুভূতি বোধ করি। :-)
জেসন বেকার

4
আমি সাধারণত লিখুন fixযেমন fix f = f (fix f)। সংক্ষিপ্ত, সাধারণ, কাজগুলি এবং গাণিতিক সংজ্ঞা অনুসারে অভিন্ন।
newacct

20
@ ন্যাভ্যাক্ট, হ্যাঁ আমি এটি সম্পর্কেও কীভাবে ভাবছি। তবে এখানে একটি আরও কার্যকর কাঠামো তৈরি করতে পারে। আপনি যদি মূল্যায়ন করেন, বলুন, আপনি পার্থক্যটি দেখতে পাচ্ছেন fix (1:) !! (10^8)। আসলটি ধ্রুব স্মৃতিতে এটি করে, আপনার লিনিয়ার মেমরি লাগে (এটি এটিকে কিছুটা ধীর করে তোলে)। এটি হ'ল "একটি শক্ত নটকে বাঁধুন" ব্যবহার করে, এবং একটি বিজ্ঞপ্তি তথ্য কাঠামো তৈরি করার অনুমতি দেয়, যেখানে আপনার হয় না।
লুকি

22
আপনি আবার নতুন উদ্ভাবন fixকরতে পারে! আমাকে fixঅনেক কিছু বুঝতে সাহায্য করেছে
ফ্রেডওভারফ্লো

উত্তর:


91

আপনি কিছু ভুল করছেন না। fix idএকটি অসীম লুপ।

যখন আমরা বলি যে fixকোনও ফাংশনের সর্বনিম্ন স্থির বিন্দুটি ফিরে আসে, তখন আমাদের অর্থ ডোমেন তত্ত্বের অর্থে that সুতরাং fix (\x -> 2*x-1)হয় না ফিরে যাচ্ছে 1, কারণ যদিও 1যে ফাংশন একটি নির্দিষ্ট বিন্দু, তাই নয় কি অন্তত ডোমেইন ক্রম এক।

আমি কেবলমাত্র দু'একটি অনুচ্ছেদে ডোমেন অর্ডার করার বর্ণনা দিতে পারি না, তাই আমি আপনাকে উপরের ডোমেন তত্ত্বের লিঙ্কটিতে উল্লেখ করব। এটি একটি দুর্দান্ত টিউটোরিয়াল, পড়তে সহজ এবং বেশ আলোকিত। আমি এটি সুপারিশ।

10,000 ফুট থেকে দেখার জন্য, fixএকটি উচ্চ-অর্ডার ফাংশন যা পুনরাবৃত্তির ধারণাটিকে এনকোড করে । আপনার যদি প্রকাশ হয়:

let x = 1:x in x

যা অসীম তালিকার ফলাফল [1,1..], আপনি একই জিনিসটি ব্যবহার করে বলতে পারেন fix:

fix (\x -> 1:x)

(অথবা কেবল fix (1:)), যা আমাকে একটি নির্দিষ্ট বিন্দু এটি বলছেন (1:)ফাংশন, IOW একটি মান xযেমন যে x = 1:x... ঠিক মত আমরা উপরে বর্ণিত। আপনি সংজ্ঞা থেকে দেখতে পারেন, fixএই ধারণা ছাড়া আর কিছুই নয় - পুনরাবৃত্তি একটি ফাংশনে আবদ্ধ হয়।

এটিও পুনরাবৃত্তির সত্যিকারের একটি সাধারণ ধারণা - আপনি বহুগঠিত পুনরাবৃত্তি ব্যবহার করে এমন ফাংশনগুলি সহ এইভাবে কোনও পুনরাবৃত্ত ফাংশন লিখতে পারেন । সুতরাং উদাহরণস্বরূপ টিপিক্যাল ফিবোনাচি ফাংশন:

fib n = if n < 2 then n else fib (n-1) + fib (n-2)

fixএভাবে ব্যবহার করে লেখা যায় :

fib = fix (\f -> \n -> if n < 2 then n else f (n-1) + f (n-2))

অনুশীলন: fixএই দুটি সংজ্ঞা fibসমান কিনা তা দেখানোর সংজ্ঞাটি প্রসারিত করুন ।

তবে সম্পূর্ণ বোঝার জন্য, ডোমেন তত্ত্ব সম্পর্কে পড়ুন। এটা সত্যিই দুর্দান্ত জিনিস।


32
এখানে ভাবার একটি সম্পর্কিত উপায় fix id: fixটাইপ একটি ফাংশন লাগে a -> aএবং টাইপের একটি মান প্রদান করে a। যেহেতু যে কারও idজন্য বহুমুখী a, fix idএর ধরণ থাকবে a, অর্থাত্ কোনও সম্ভাব্য মান। হাসকেলে, একমাত্র মান যা কোনও প্রকারের হতে পারে তা নীচে, ⊥, এবং একটি নন-টার্মিনেটিং গণনা থেকে পৃথক। সুতরাং fix idসঠিকভাবে এটি উত্পাদন করা উচিত, নীচের মান। একটি বিপদ fixহ'ল যদি ⊥ আপনার ফাংশনের একটি স্থির বিন্দু হয়, তবে এটি সংজ্ঞা অনুসারে সর্বনিম্ন নির্দিষ্ট পয়েন্ট হয়, সুতরাং শেষ fixহবে না।
জন এল

4
হাস্কেলের জোনএলও যে undefinedকোনও ধরণের মান। আপনি সংজ্ঞায়িত করতে fixহিসাবে: fix f = foldr (\_ -> f) undefined (repeat undefined)
didest

4
@ ডিগো আপনার কোডটির সমতুল্য _Y f = f (_Y f)
নেস

25

আমি এটুকু বোঝার দাবি করি না, তবে এটি যদি কাউকে সাহায্য করে ... তবে ইয়েপি।

সংজ্ঞা বিবেচনা করুন fixfix f = let x = f x in x। মন-বগল অংশটি যে xহিসাবে সংজ্ঞায়িত করা হয় f x। তবে এক মিনিটের জন্য এটি সম্পর্কে চিন্তা করুন।

x = f x

যেহেতু x = fx, তারপরে আমরা xতার ডান হাতের মানটি ঠিক করতে পারি? তাহলে...

x = f . f $ x -- or x = f (f x)
x = f . f . f $ x -- or x = f (f (f x))
x = f . f . f . f . f . f . f . f . f . f . f $ x -- etc.

সুতরাং কৌতুকটি শেষ করার জন্য, fকিছু ধরণের কাঠামো তৈরি করতে হবে, যাতে পরবর্তী সময়ে fসেই কাঠামোর সাথে মেলে এবং পুনরাবৃত্তিটি শেষ করতে পারে, প্রকৃতপক্ষে তার প্যারামিটারের পূর্ণ "মান" সম্পর্কে চিন্তা না করেই (?)

অবশ্যই, যদি না আপনি লুকি চিত্রিত হিসাবে অসীম তালিকা তৈরির মতো কিছু করতে চান।

টমএমডির ফ্যাক্টরিয়াল ব্যাখ্যা ভাল। ফিক্সের ধরণের স্বাক্ষর (a -> a) -> a। জন্য টাইপ স্বাক্ষর (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1)হয় (b -> b) -> b -> b, অন্য কথায়, (b -> b) -> (b -> b)। সুতরাং আমরা এটা বলতে পারি a = (b -> b)। এইভাবে, ফিক্সটি আমাদের ফাংশনটি গ্রহণ করে, যা হয় a -> a, বা সত্যই (b -> b) -> (b -> b), এবং aঅন্য কথায়, অন্য ক্রিয়ায়, টাইপের ফলাফলটি ফিরিয়ে b -> bদেয়!

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

মনে রাখবেন কীভাবে আমি বলেছিলাম যে fকোনও ধরণের কাঠামো তৈরি করতে হয়েছিল যাতে fপরেরটি মেলে এবং শেষ হতে পারে? ঠিক আছে যে ঠিক ঠিক না, আমার ধারণা। টমএমডি চিত্রিত করেছেন যে কীভাবে আমরা xফাংশনটি প্রয়োগ করতে এবং বেস কেসের দিকে এগিয়ে যেতে পারি। তার ফাংশনটির জন্য, তিনি যদি / তারপর ব্যবহার করেন এবং এটিই সমাপ্তির কারণ হয়। পুনরাবৃত্তি প্রতিস্থাপনের পরে, শেষ পর্যন্ত inসম্পূর্ণ সংজ্ঞাটির অংশটি fixসংজ্ঞায়িত হওয়া বন্ধ করে দেয় xএবং এটি তখনই হয় যখন এটি গণনীয় এবং সম্পূর্ণ হয়।


ধন্যবাদ এটি একটি খুব দরকারী এবং ব্যবহারিক ব্যাখ্যা।
kizzx2

18

ফিক্সপয়েন্টটি শেষ করার জন্য আপনার একটি উপায় দরকার। আপনার উদাহরণটি প্রসারিত করা সুস্পষ্ট যে এটি শেষ হবে না:

fix id
--> let x = id x in x
--> id x
--> id (id x)
--> id (id (id x))
--> ...

এখানে ফিক্স ব্যবহারের আমার একটি বাস্তব উদাহরণ রয়েছে (নোট যে আমি প্রায়শই ফিক্স ব্যবহার করি না এবং সম্ভবত ক্লান্ত হয়ে পড়েছিলাম / যখন আমি এটি লিখেছিলাম তখন পঠনযোগ্য কোড সম্পর্কে চিন্তিত নন):

(fix (\f h -> if (pred h) then f (mutate h) else h)) q

ডব্লিউটিএফ, আপনি বলেন! হ্যাঁ, তবে এখানে কয়েকটি কার্যকর পয়েন্ট রয়েছে। প্রথমত, আপনার প্রথম fixযুক্তিটি সাধারণত একটি ফাংশন হওয়া উচিত যা 'পুনরাবৃত্তি' কেস এবং দ্বিতীয় যুক্তিটি সেই ডেটা যা সেই বিষয়ে কাজ করা উচিত। এখানে নামযুক্ত ফাংশন হিসাবে একই কোড:

getQ h
      | pred h = getQ (mutate h)
      | otherwise = h

আপনি যদি এখনও বিভ্রান্ত থাকেন তবে সম্ভবত ঘটনাচক্রে এটি একটি সহজ উদাহরণ হতে পারে:

fix (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1) 5 -->* 120

মূল্যায়ন লক্ষ্য করুন:

fix (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1) 3 -->
let x = (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1) x in x 3 -->
let x = ... in (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1) x 3 -->
let x = ... in (\d -> if d > 0 then d * (x (d-1)) else 1) 3

ওহ, আপনি কি তা দেখেছেন? যে xআমাদের ভিতরে একটি ফাংশন ওঠে thenশাখা।

let x = ... in if 3 > 0 then 3 * (x (3 - 1)) else 1) -->
let x = ... in 3 * x 2 -->
let x = ... in 3 * (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1) x 2 -->

উপরের দিকে আপনার মনে রাখা দরকার x = f x, সুতরাং ন্যায়বিচারের x 2পরিবর্তে শেষে দুটি যুক্তি 2

let x = ... in 3 * (\d -> if d > 0 then d * (x (d-1)) else 1) 2 -->

আর আমি এখানেই থামব!


আপনার উত্তরটি আসলে fixআমার কাছে বোধগম্য হয়েছিল। আমার উত্তর মূলত আপনি ইতিমধ্যে যা বলেছেন তার উপর নির্ভর করে depends
ড্যান বার্টন

@ থমাস উভয় আপনার হ্রাস ক্রমটি ভুল are :) id xকেবল হ্রাস করে x(যা এরপরে ফিরে আসে id x)। - তারপরে, ২ য় নমুনা ( fact) এ, যখন প্রথমে xথাঙ্কটি বাধ্য করা হবে, ফলস্বরূপ মানটি স্মরণ করে পুনরায় ব্যবহার করা হবে। ভাগ করে নেওয়ার সংজ্ঞা (\recurse ...) xদিয়ে পুনরায় গণনাটি হবে , এই ভাগ করে নেওয়ার সংজ্ঞা দিয়ে নয় । - আমি এখানে পরীক্ষার সম্পাদনা করেছি - আপনি এটি ব্যবহার করতে আপনাকে স্বাগতম, বা আপনি যদি অনুমোদন করেন তবে আমি সম্পাদনাটি করতে পারি। y g = g (y g)fix
নেস

আসলে, যখন fix idহ্রাস করা let x = id x in xহয় id xতখন letফ্রেমের অভ্যন্তরে অ্যাপ্লিকেশনের মানকেও চাপ দেয় (থাঙ্ক), সুতরাং এটি হ্রাস করে let x = x in xএবং এই লুপগুলি। দেখতে এটার মত.
নেস

সঠিক। আমার উত্তরটি সমীকরণীয় যুক্তি ব্যবহার করছে। লা হ্যাসেলকে হ্রাস দেখানো হচ্ছে যা মূল্যায়ন আদেশের সাথে নিজেকে উদ্বেগিত করে, কেবল কোনও সত্যিকারের লাভ ছাড়াই উদাহরণটিকে বিভ্রান্ত করে তোলে।
থমাস এম ডুবুইসন

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

3

আমি এটি কীভাবে বুঝতে পারি এটি এটি ফাংশনটির জন্য একটি মান সন্ধান করে, যেমন এটি আপনাকে দেবে একই জিনিসটিকে আউটপুট করে। ক্যাচটি হ'ল, এটি সর্বদা অপরিজ্ঞাত (বা একটি অসীম লুপ, হ্যাস্কেল, অপরিজ্ঞাত এবং অসীম লুপগুলি একই) বা যেটির মধ্যে সর্বাধিক অপরিজ্ঞাত রয়েছে তা বেছে নেবে। উদাহরণস্বরূপ, আইডি সহ,

λ <*Main Data.Function>: id undefined
*** Exception: Prelude.undefined

আপনি দেখতে পাচ্ছেন fixযে অপরিবর্তিত একটি নির্দিষ্ট পয়েন্ট, তাই এটি বেছে নেবে। আপনি যদি এর পরিবর্তে করেন (\ x-> 1: x)।

λ <*Main Data.Function>: undefined
*** Exception: Prelude.undefined
λ <*Main Data.Function>: (\x->1:x) undefined
[1*** Exception: Prelude.undefined

সুতরাং fixঅপরিশোধিত বাছাই করতে পারবেন না। এটিকে অসীম লুপগুলির সাথে আরও কিছুটা যুক্ত করতে।

λ <*Main Data.Function>: let y=y in y
^CInterrupted.
λ <*Main Data.Function>: (\x->1:x) (let y=y in y)
[1^CInterrupted.

আবার কিছুটা পার্থক্য। তাহলে নির্দিষ্ট পয়েন্টটি কী? আমাদের চেষ্টা করুন repeat 1

λ <*Main Data.Function>: repeat 1
[1,1,1,1,1,1, and so on
λ <*Main Data.Function>: (\x->1:x) $ repeat 1
[1,1,1,1,1,1, and so on

এটি একই! যেহেতু এটিই একমাত্র স্থির বিন্দু, তাই এটি fixঅবশ্যই স্থির করে নিন। দুঃখিত fix, আপনার জন্য কোনও অসীম লুপ বা অপরিবর্তিত নেই।

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