كيف 'الحصول على' الواقع / الحصول على / الدولة الأولى في حزقيل؟

StackOverflow https://stackoverflow.com/questions/1036957

  •  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، وما إلى ذلك)، وأدركت أن حتى الآن هيكل الرقابة الأكثر شيوعا كان مجرد وضع بيان واحد قبل الآخر. استغرق الأمر سنة من دراسة هاسكل قبل أدركت أنه حتى كان هيكل الرقابة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top