簡體   English   中英

Haskell Monad狀態示例

[英]Haskell Monad State Example

我正在嘗試使用Haskell的Control.Monad.State ,嘗試迭代字符串或整數的列表,計算它們,並用整數0替換字符串條目。 我已設法完成計數部分,但未能創建替換列表。 這是我的代碼正確打印[3,6]到屏幕。 如何創建所需的列表[6,0,3,8,0,2,9,1,0]

module Main( main ) where

import Control.Monad.State

l = [
    Right 6,
    Left "AAA",
    Right 3,
    Right 8,
    Left "CCC",
    Right 2,
    Right 9,
    Right 1,
    Left "D"]

scanList :: [ Either String Int ] -> State (Int,Int) [ Int ]
scanList [    ] = do
    (ns,ni) <- get
    return (ns:[ni])
scanList (x:xs) = do
    (ns,ni) <- get
    case x of
        Left  _ -> put (ns+1,ni)
        Right _ -> put (ns,ni+1)
    case x of
        Left  _ -> scanList xs -- [0] ++ scanList xs not working ...
        Right i -> scanList xs -- [i] ++ scanList xs not working ...

startState = (0,0)

main = do
    print $ evalState (scanList l) startState

[0] ++ scanList xs不起作用,因為scanList xs不是列表,而是State (Int,Int) [Int] 要解決此問題,您需要使用fmap / <$>

您還需要更改基本情況,以使狀態值不是返回值。

scanList :: [Either String Int] -> State (Int, Int) [Int]
scanList []     = return []
scanList (x:xs) = do
    (ns,ni) <- get
    case x of
        Left  _ -> put (ns+1, ni)
        Right _ -> put (ns, ni+1)
    case x of
        Left  _ -> (0 :) <$> scanList xs
        Right i -> (i :) <$> scanList xs

但是,為了進一步簡化代碼,最好使用mapM / traversestate來刪除遞歸和get / put語法的大部分樣板。

scanList :: [Either String Int] -> State (Int, Int) [Int]
scanList = mapM $ \x -> state $ \(ns, ni) -> case x of
    Left  _ -> (0, (ns+1, ni))
    Right i -> (i, (ns, ni+1))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM