簡體   English   中英

定義haskell函數[IO a]-> IO [a]

[英]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.

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