मेरे पास कुछ कोड है जो आदिम कार्यक्रमों का मूल्यांकन करता है। कार्यक्रम बयानों की एक सूची है (अभिव्यक्ति, ब्लॉक, वापसी कथन)। मूल्यांकन का परिणाम अंतिम मूल्यांकन अभिव्यक्ति है। इसके अलावा मूल्यांकनकर्ता को return
कथन का ठीक से इलाज करना चाहिए (यानी return
की पहली घटना के बाद मूल्यांकन रोकना)।निरंतरता के साथ कोड पुनर्लेखन
इस तर्क को लागू करने के लिए मैं विशेष कॉलबैक फ़ंक्शन (NextStep
) पास करता हूं जो वर्तमान विवरण के बाद अगला मूल्यांकन चरण बनाता है।
data Statement =
Expr Int
| Block [Statement]
| Return Int
deriving (Show, Eq)
data Value =
Undefined
| Value Int
deriving (Show, Eq)
type NextStep = Value -> Value
evalStmt :: Statement -> NextStep -> Value
evalStmt (Expr val) next =
let res = Value val
in next res
evalStmt (Block stmts) next = evalBlock stmts next
evalStmt (Return val) next = Value val
evalBlock :: [Statement] -> NextStep -> Value
evalBlock [] next = next Undefined
evalBlock [st] next = evalStmt st next
evalBlock (st:rest) next = evalStmt st $ \ _ -> evalBlock rest next
evalProgram stmts = evalBlock stmts id
prog1 = [Expr 1, Block [Return 3, Expr 2], Expr 4]
evalProg1 = evalProgram prog1 -- result will be Value 3
सवाल यह है कि मैं निरंतरता इकाई के साथ इस कोड को फिर से लिखने सकता है: जब वापसी कथन से निपटने मैं अगले कदम कहें? मैं evalStmt
और evalBlock
कार्यों में स्पष्ट रूप से पास NextStep
कॉलबैक से छुटकारा पाना चाहता हूं। क्या यह संभव है?
'Cont' के लिए मोनैड इंस्टेंस को इस तरह श्रृंखला में परिभाषित किया गया है, ताकि * केवल * evalBlock (st: rest) = evalStmt st के बराबर होना चाहिए ... evalBlock rest' –
@ ØrjanJohansen काफी सही! – jozefg