[英]Haskell sequence of IO actions processing with filtration their results in realtime+perfoming some IO actions in certain moments
I want to do some infinite sequence of IO actions processing with filtration their results in realtime+perfoming some IO actions in certain moments: We have some function for reducing sequences (see my question haskell elegant way to filter (reduce) sequences of duplicates from infinte數字列表):
f :: Eq a => [a] -> [a]
f = map head . group
和表達
join $ sequence <$> ((\l -> (print <$> l)) <$> (f <$> (sequence $ replicate 6 getLine)))
如果我們運行它,用戶可以生成任何數字序列,例如:
1
2
2
3
3
"1"
"2"
"3"
[(),(),()]
這意味着首先執行所有 getLine 操作(在示例中為 6 次,最后執行所有 IO 操作以執行過濾列表,但我想恰好在時刻執行 IO 操作,然后排序減少對相同數字的某些子序列完成.
如何存檔此 output:
1
2
"1"
2
3
"2"
3
3
"3"
[(),(),()]
所以我希望這個表達式不掛起:
join $ sequence <$> ((\l -> (print <$> l)) <$> (f <$> (sequence $ repeat getLine)))
如何按上述方式歸檔實時 output 而不會在無限列表中阻止它?
這似乎是流媒體庫的工作,例如流媒體。
{-# LANGUAGE ImportQualifiedPost #-}
module Main where
import Streaming
import Streaming.Prelude qualified as S
main :: IO ()
main =
S.mapM_ print
. S.catMaybes
. S.mapped S.head
. S.group
$ S.replicateM 6 getLine
“流”有一個 API 讓人想起列表,但適用於有效的序列。
流式group
版本的好處在於,如果不需要,它不會強迫您將整個組保留在 memory 中。
此答案中最不直觀的 function 是mapped
,因為它非常通用。 流式傳輸的head
版本是否適合作為其參數並不明顯。 關鍵思想是Stream
類型既可以表示正常有效序列,也可以表示已划分組的元素序列。 這是通過更改仿函數類型參數來控制的( Of
在第一種情況下,嵌套Stream (Of a) m
在分組Stream
s的情況下)。
mapped
讓您在對底層 monad 產生一些影響的同時轉換該函子參數(此處IO
)。 head
處理內部Stream (Of a) m
組,讓我們回到Of (Maybe a)
函子參數。
如果沒有第三方庫,您可以懶惰地讀取標准輸入的內容,在預期輸入的末尾附加一個虛擬字符串以強制 output。 (可能有一個更好的解決方案,我愚蠢地忽略了。)
import System.IO
print_unique :: (String, String) -> IO ()
print_unique (last, current) | last == current = return ()
| otherwise = print last
main = do
contents <- take 6 <$> lines <$> hGetContents stdin
traverse print_unique (zip <*> tail $ (contents ++ [""]))
zip <*> tail
生成由第i
行和第i+1
行組成的元組,而不會阻塞。 如果以下行不同,則print_unique
然后立即輸出一行。
本質上,您是在執行輸入時對 output 操作進行排序,而不是對輸入操作進行排序。
我用 iterateUntilM 找到了一個很好的解決方案
iterateUntilM (\_->False) (\pn -> getLine >>= (\n -> if n==pn then return n else (if pn/="" then print pn else return ()) >> return n) ) ""
我不喜歡冗長的
(if pn/="" then print pn else return ())
如果您知道如何減少這種情況,請發表評論)
附言。 值得注意的是,我制作了一個關於這個 function 的視頻:) 並不能立即應用它:(
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.