كيف 'الحصول على' الواقع / الحصول على / الدولة الأولى في حزقيل؟
-
10-07-2019 - |
سؤال
ولدي وظيفة:
test :: String -> State String String
test x =
get >>= \test ->
let test' = x ++ test in
put test' >>
get >>= \test2 -> put (test2 ++ x) >>
return "test"
وأستطيع أن أفهم حد كبير ما يحدث في جميع أنحاء هذه الوظيفة، وأنا بدءا من الحصول على تعليق من الكائنات الدقيقة الاحاديه الخلية. ما لا أفهمه هو كيف ومتى أركض هذا:
runState (test "testy") "testtest"
وظيفة "الحصول على 'في' اختبار 'بطريقة ما يحصل الحالة الأولية" testtest ". يمكن للشخص كسر هذه القاعده وشرح لي؟
وأنا أقدر الردود!
المحلول
وكنت ذاهبا في الأصل لهذا المنصب بمثابة تعليق، لكنه قرر شرح أكثر قليلا.
وبالمعنى الدقيق للكلمة، get
لا "اتخاذ" حجة. أعتقد أن ملثمين الكثير من ما يجري من قبل ما كنت لا ترى - التعاريف مثيل من الكائن الدقيق الاحادي الخلية الدولة
وget
هو في الواقع طريقة الطبقة MonadState. في الكائن الدقيق الاحادي الخلية الدولة هو مثيل MonadState، وتوفير التعريف التالي للget
:
get = State $ \s -> (s,s)
وبعبارة أخرى، get
يعود مجرد الكائن الدقيق الاحادي الخلية الأساسية للغاية الدولة (تذكر أن الكائن الدقيق الاحادي الخلية يمكن التفكير فيه باعتباره "المجمع" لحساب)، حيث أي s
مساهمة في حساب سيعود زوج من s
نتيجة .
ووالشيء التالي الذي تحتاجه هو أن ننظر إلى >>=
، الذي يحدد الدولة هكذا:
m >>= k = State $ \s -> let
(a, s') = runState m s
in runState (k a) s'
وهكذا، >>=
سوف تسفر عن الحساب الجديد، الذي لن يتم حسابها حتى يحصل على الحالة الأولية (وهذا ينطبق على جميع الحسابات الدولة عندما يكونون في شكلها "ملفوفة"). ويتحقق نتيجة لهذا الحساب الجديد من خلال تطبيق كل ما هو على الجانب الأيمن من >>=
إلى نتيجة تشغيل حساب التي كانت على الجانب الأيسر. (وهذا الجملة مربكة جدا التي قد تتطلب قراءة إضافية أو اثنين).
ولقد وجدت أنه من المفيد جدا أن "desugar" كل ما يجري. وبذلك يأخذ الكثير من الكتابة، ولكن ينبغي أن الجواب على سؤالك (حيث get
يزداد من) واضحة جدا. لاحظ أن يلي ينبغي النظر psuedocode ...
test x =
State $ \s -> let
(a,s') = runState (State (\s -> (s,s))) s --substituting above defn. of 'get'
in runState (rightSide a) s'
where
rightSide test =
let test' = x ++ test in
State $ \s2 -> let
(a2, s2') = runState (State $ \_ -> ((), test')) s2 -- defn. of 'put'
in runState (rightSide2 a2) s2'
rightSide2 _ =
-- etc...
وهذا ينبغي أن تجعل من الواضح أن النتيجة النهائية لوظيفتنا هي حساب جديد للدولة التي سوف تحتاج قيمة أولية (s
) لجعل بقية الاشياء تحدث. قمت بتوفيرها s
كما "testtest"
مع دعوة runState
الخاص بك. إذا كنت بديلا "testtest" لs
في pseudocode أعلاه، سترى أن أول ما يحدث هو أننا تشغيل get
مع "testtest" باسم "الحالة الأولية". هذا ينتج ("testtest", "testtest")
وهلم جرا.
وهكذا حيث ان يحصل get
بك الأولي الدولة "testtest". ويساعد هذا الأمل!
نصائح أخرى
وقد تساعدك على أن نلقي نظرة أعمق على ما هو نوع منشئ State
حقا، وكيف يستخدم runState ذلك. في GHCi:
Prelude Control.Monad.State> :i State
newtype State s a = State {runState :: s -> (a, s)}
Prelude Control.Monad.State> :t runState
runState :: State s a -> s -> (a, s)
وState
يأخذ حجتين: نوع من الدولة، ونوع إرجاعها. ويتم تنفيذ ذلك بوصفها وظيفة أخذ الحالة الأولية وتدر قيمة العودة والدولة الجديدة.
وrunState
يأخذ هذه المهمة، والمدخلات الأولية، و(على الارجح) ينطبق فقط واحدة إلى أخرى لاسترداد (النتيجة، الدولة) زوج.
وظيفة test
الخاص بك هو تكوين كبيرة من الوظائف State
من نوع، كل أخذ إدخال الدولة والعائد على (النتيجة، الدولة) الإخراج، في الوتر بعضها البعض بطريقة المنطقي أن البرنامج. كل runState
يفعله هو توفر لهم نقطة انطلاق الدولة.
في هذا السياق، get
هو مجرد وظيفة التي تأخذ الدولة كمدخل، وإرجاع (النتيجة، الدولة) الناتج من هذا القبيل أن النتيجة هي حالة الإدخال، والدولة لم يتغير (الدولة الناتج هو حالة الإدخال ). وبعبارة أخرى، get s = (s, s)
وتمر الفصل 8 ( "موزعي الوظيفي") من البرمجة غراهام هاتون في هاسكل عدة مرات حتى كنت بشكل صحيح يفهم هو، تليها الذهاب في البرنامج التعليمي <لأ href = "http://www.haskell.org/all_about_monads/html/index.html" يختلط = "نوفولو جعل noreferrer "> كل شيء عن الكائنات الدقيقة الاحاديه الخلية ، انقر فوق هذا بالنسبة لي.
وهذه المسألة مع الكائنات الدقيقة الاحاديه الخلية هي أنها مفيدة جدا لعدة أمور أن أولئك منا يأتي من خلفية البرمجة المعتادة تجد يختلف تماما. الأمر يحتاج إلى بعض الوقت لإدراك أن التحكم في التدفق والتعامل مع دولة ليست فقط مماثلة بما فيه الكفاية بحيث يمكن التعامل معها من قبل نفس الآلية، ولكنها عندما كنت خطوة الى الوراء بعيدا بما فيه الكفاية، والشيء نفسه.
وجاء عيد الغطاس عندما كنت تفكر هياكل المراقبة في C (for
وwhile
، وما إلى ذلك)، وأدركت أن حتى الآن هيكل الرقابة الأكثر شيوعا كان مجرد وضع بيان واحد قبل الآخر. استغرق الأمر سنة من دراسة هاسكل قبل أدركت أنه حتى كان هيكل الرقابة.