[英]Define a haskell function [IO a] -> IO[a]
我正在做一次haskell練習,關於定義一個函數accumise :: [IO a]-> IO [a],該函數執行一系列交互並將其結果存儲在列表中。
讓我感到困惑的是如何表達IO列表? (動作:動作)??
如何使用IO編寫遞歸代碼?
這是我的代碼,但是這些存在一些問題...
accumulate :: [IO a] -> IO [a]
accumulate (action:actions) = do
value <- action
list <- accumulate (action:actions)
return (convert_to_list value list)
convert_to_list:: Num a =>a -> [a]-> [a]
convert_to_list a [] = a:[]
convert_to_list x xs = x:xs
您要實現的是Control.Monad
sequence
。
只是為了讓你找到答案,而不是給它,嘗試搜索[IO a] -> IO [a]
上hoogle (有,當你選擇了一個功能頁面的右手邊源鏈接)。
嘗試在代碼中查看當動作列表為空列表時會發生什么,並查看序列做了什么來解決這一問題。
Control.Monad
已經有這樣的函數,它稱為sequence
(不,您不應該看它)。 您應該指出在命名過程中做出的重要決定。 從技術上講, [IO a]
沒有說明這些Monad
應該以什么順序彼此連接,但是名稱sequence
賦予了順序連接的含義。
至於解決你的問題。 我建議多看一些類型,並建議@sacundim。 在GHCi(格拉斯哥Haskell編譯器的解釋器)中,有一種非常不錯的方法來檢查類型,從而理解表達式( :t (:)
將返回(:) :: a -> [a] -> [a]
,這應該提醒您一個您自己的函數,但限制類型較少)。
首先,我將嘗試通過更簡單的示例查看您所顯示的內容。
data MyWrap a = MyWrap a
accumulate :: [MyWrap a] -> MyWrap [a]
accumulate (action:actions) = MyWrap (convert_to_list value values) where
MyWrap value = action -- use the pattern matching to unwrap value from action
-- other variant is:
-- value = case action of
-- MyWrap x -> x
MyWrap values = accumulate (action:actions)
我犯了與您有意犯的錯誤相同的錯誤,但差異很小( values
只是一個提示)。 正如您可能已經被告知的,您可以嘗試通過內聯適當的函數定義來嘗試解釋任何程序。 即,匹配等號( =
)左側的定義,並將其替換為右側。 您的情況是無限循環的。 嘗試在這個樣本或您的樣本上解決它,我想您會明白的(但是您的問題可能只是錯字)。
更新:當您的程序在運行時落入有關模式匹配的消息時,請不要害怕。 當您將函數調用為accumulate []
時,請考慮一下情況
可能您正在尋找映射[ma] -> m [a]
sequence
函數?
因此,對於您的問題的答案的簡短版本是,您的代碼幾乎沒有錯誤。
首先,它進行類型檢查:
Prelude> let accumulate (action:actions) = do { value <- action ;
list <- accumulate (action:actions) ; return (value:list) }
Prelude> :t accumulate
accumulate :: (Monad m) => [m t] -> m [t]
為什么在那里使用return (value:list)
? 看第二個函數,它只是(:)
。 叫g
g a [] = a:[]
g a xs = a:xs
與使用相同參數調用(:)
相同。 這就是所謂的“ eta縮減”: (\\x-> gx) === g
(讀===
為“等價”)。
所以現在您的代碼只剩下一個問題。 您已經從操作中取出了值value <- action
,那么為什么要在list <- accumulate (action:actions)
重用該操作? 你真的必須嗎? 現在你有,例如
accumulate [a,b,c] ===
do { v1<-a; ls<-accumulate [a,b,c]; return (v1:ls) } ===
do { v1<-a; v2<-a; ls<-accumulate [a,b,c]; return (v1:v2:ls) } ===
do { v1<-a; v2<-a; v3<-a; ls<-accumulate [a,b,c]; return (v1:v2:v3:ls) } ===
.....
一個簡單的修復程序,您就在那里。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.