Hơi bị hoang mang bởi đoạn mã sau. Trong phiên bản không đồ chơi của vấn đề tôi đang cố gắng để làm một tính toán monadic trong một kết quả đơn nguyên, các giá trị trong đó chỉ có thể được xây dựng từ bên trong IO. Có vẻ như ma thuật đằng sau IO làm cho tính toán như vậy nghiêm ngặt, nhưng tôi không thể tìm ra chính xác điều đó xảy ra như thế nào.IO monad ngăn chặn ngắn mạch của bản đồ nhúngM?
Mã:
data Result a = Result a | Failure deriving (Show)
instance Functor Result where
fmap f (Result a) = Result (f a)
fmap f Failure = Failure
instance Applicative Result where
pure = return
(<*>) = ap
instance Monad Result where
return = Result
Result a >>= f = f a
Failure >>= _ = Failure
compute :: Int -> Result Int
compute 3 = Failure
compute x = traceShow x $ Result x
compute2 :: Monad m => Int -> m (Result Int)
compute2 3 = return Failure
compute2 x = traceShow x $ return $ Result x
compute3 :: Monad m => Int -> m (Result Int)
compute3 = return . compute
main :: IO()
main = do
let results = mapM compute [1..5]
print $ results
results2 <- mapM compute2 [1..5]
print $ sequence results2
results3 <- mapM compute3 [1..5]
print $ sequence results3
let results2' = runIdentity $ mapM compute2 [1..5]
print $ sequence results2'
Sản lượng:
1
2
Failure
1
2
4
5
Failure
1
2
Failure
1
2
Failure
Cảm ơn bạn rất nhiều vì câu trả lời của bạn, chi. Tôi có thể hỏi làm thế nào bạn biết rằng định nghĩa IO của mapM là nghiêm ngặt và trả lại là lười biếng? – NioBium
@NioBium 'Failure >> = f = Failure' loại bỏ' f': không cần tiến xa hơn vào chuỗi monadic. IO có định nghĩa đòn bẩy thấp hơn không dễ viết, nhưng - ngoại lệ chặn - 'action >> = f' sẽ luôn gọi' f' vì người ta kỳ vọng rằng ví dụ 'action >> print 4' cuối cùng sẽ in 4 bất kể' action' làm gì (chặn các ngoại lệ IO và không kết thúc). – chi
Phải. Cảm ơn một lần nữa! – NioBium