Tôi biết rằng Haskell củaScala tương đương do-ký hiệu của Haskell (một lần nữa)
do
x <- [1, 2, 3]
y <- [7, 8, 9]
let z = (x + y)
return z
thể được thể hiện trong Scala như
for {
x <- List(1, 2, 3)
y <- List(7, 8, 9)
z = x + y
} yield z
Nhưng, đặc biệt là với monads, Haskell thường có câu lệnh bên trong do
khối không tương ứng với <-
hoặc =
. Ví dụ, đây là một số mã từ Pandoc sử dụng Parsec để phân tích cú pháp một cái gì đó từ một chuỗi.
-- | Parse contents of 'str' using 'parser' and return result.
parseFromString :: GenParser tok st a -> [tok] -> GenParser tok st a
parseFromString parser str = do
oldPos <- getPosition
oldInput <- getInput
setInput str
result <- parser
setInput oldInput
setPosition oldPos
return result
Như bạn có thể thấy, nó lưu vị trí và đầu vào, chạy phân tích cú pháp trên chuỗi, và sau đó phục hồi các đầu vào và vị trí trước khi trở về kết quả.
Tôi không thể cho cuộc sống của tôi tìm ra cách dịch setInput str
, setInput oldInput
và setPosition oldPos
vào Scala. Tôi nghĩ rằng nó sẽ làm việc nếu tôi chỉ cần đặt biến điều vô lý trong vì vậy tôi có thể sử dụng <-
, như
for {
oldPos <- getPosition
oldInput <- getInput
whyAmIHere <- setInput str
result <- parser
...
} yield result
nhưng tôi không chắc chắn đó là trường hợp, và nếu nó là đúng, tôi chắc chắn rằng phải có một cách tốt hơn để làm điều này. Ồ, và nếu bạn có thể trả lời câu hỏi này, bạn có thể trả lời thêm một câu hỏi nữa không: tôi phải nhìn chằm chằm vào Monads bao lâu trước khi họ không cảm thấy như ma thuật đen? :-)
Cảm ơn! Todd
Nếu bạn không dùng quy mô để sử dụng biến, bạn có thể thay thế tên bằng dấu gạch dưới: '_ <- setInput str' – incrop
Tôi đoán đó là cách giống như Scala nhất để làm điều đó. – TOB
Không chắc chắn nó sẽ thực sự có thể, nhưng điều này có thể trông tự nhiên hơn bằng cách di chuyển các phát biểu này vào phần thân của for, nơi bạn thực sự có thể đi theo kiểu thủ tục. – dividebyzero