هل يمكن لأي شخص أن يمشي لي من خلال وظيفة هاسكل هذه (المرتبطة بالدولة)؟

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

  •  22-09-2019
  •  | 
  •  

سؤال

tick :: State Int Int
tick = get >>= \n ->
       put (n+1) >>= \y ->
       return n

أنا في حيرة من أمرك كيف put (n+1) له أي تأثير على النتيجة النهائية لهذه الوظيفة على الإطلاق. يبدو أن هذه الوظيفة يجب أن تعيد الحالة الأولية دون تغيير. أحاول أن أركض هذا في ذهني ، لكنني أظل نفاد الغرفة لأمسك الأشياء في مكانها. :

إذا تمكن شخص ما من المشي لي خلال تقييم هذه الوظيفة ، فسيكون ذلك مفيدًا حقًا.

هل كانت مفيدة؟

المحلول

... كيف يضع تحديث الدولة في المقام الأول؟ يبدو أنه يجلس هناك لا يفعل شيئًا ...

آه ، الآن أفهم سؤالك. أنت تتساءل كيف putget) العمل ، أليس كذلك؟

ربما يساعد مثال في JavaScript (لغة ذات حالة قابلة للتغيير الفعلية):

var s; // mutable state
function get() { return s; }
function put(x) { s = x; }

function tick() {
    var n = get();
    put(n + 1);
    return n;
}

آمل أن يوضح هذا ذلك ، بينما n لا تتغير ، لا تزال الحالة الداخلية يتم تحديثها. إذا قمت بتنفيذ tick() مرتين ، سيتم زيادة الدولة مرتين.

للعودة إلى Haskell ، إليك التعريف الكامل لـ (الأجزاء ذات الصلة) State موناد:

newtype State s a = State { runState :: s -> (a, s) }

instance Monad (State s) where
    return a = State $ \s -> (a, s)
    m >>= k  = State $ \s -> let
        (a, r) = runState m s
        in runState (k a) r

get   = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)

حاول الآن توسيعك tick مثال أكثر من ذلك عن طريق الإضفاء >>=, return, get و put. نأمل أن يصبح أكثر وضوحا كيف تعمل الدولة.

نصائح أخرى

أنت على حق تمامًا. نتائج tick "الوظيفة" هي القيمة الأولية للدولة.

الآن بالطبع ، tick ليست "الوظيفة" الحقيقية ، ولكن حساب يمكنه القراءة والكتابة دولة قبل إنتاج نتيجة.
في هذه الحالة ، دولة تم تحديثه ، لكنك لا تزال تعيد القيمة الأصلية للحالة:

-- 4 is the inital state
ghci> runState tick 4
(4, 5)
-- 4 is the result of the tick computation, 5 is the updated state

في هذه الحالة ، نظرًا لأنك لا تفحص الدولة مرة أخرى في الداخل tick, ، أنت لا ترى الحالة المتغيرة. ومع ذلك ، إذا حدث بعض الحساب الآخر بعد tick, ، يمكن أن ترى الحالة المحدثة.

على سبيل المثال ، القيام به tick مرتين (ستقرأ الحالة الثانية الحالة المحدثة):

-- 4 is the inital state
ghci> runState (tick >> tick) 4
(5, 6)
-- 5 is the result of the tick computation executed twice,
-- 6 is the updated state

قد يساعد في كتابته باستخدام do الرموز

tick :: State Int Int
tick = do
    n <- get    -- get the state
    put (n+1)   -- save an incremented state
    return n    -- return the original state

بينما ال put (n+1) لا يؤثر على نتيجة الحساب ، فإنه يغير الحالة التي يتم عقدها داخل موناد الولاية.

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