我正在嘗試做一些編程,我無法進入單子。我已經提前了一點IO功能,但現在我肯定輸了...哈斯克爾monad返回類型
我有一個從網絡加載的XML字符串(所以它「存儲」在IO String
)。因此,我需要一個do
塊來加載到普通字符串。
foo :: IO String -> Nothing
foo xmlio = do
xmlio <- xml
-- do some magic
我已經實現了另一個接受純字符串並返回純XML元素的函數。它做得更多一些,但讓我們簡化一下,因爲這個問題並不重要。
import Text.XML.Light
import Text.XML.Light.Input
toxml :: String -> Maybe Element
toxml s = parseXMLDoc s
現在,我想這兩個結合起來,接受一個IO String,並返回一個「IO元素」。
toxmlio :: IO String -> ??? Maybe Element
toxmlio s = do
pures <- s
let toReturn = parseXMLDoc s
return s
返回函數的類型是(根據ghci中):
let foo = "<foo>bar</foo>"
:t return (parseXMLDoc foo)
>> return (parseXMLDoc foo) :: Monad m => m (Maybe Element)
但是,如果我改變我的函數的頭
toxmlio :: IO String -> Monad (Maybe Element)
toxmlio s = do
pures <- s
let toReturn = parseXMLDoc s
return s
我得到一個編譯錯誤
Kind mis-match
The first argument of `Monad' should have kind `* -> *',
but `Maybe Element' has kind `*'
In the type signature for `xmlio':
xmlio :: String -> Monad (Maybe Element)
有沒有人有任何想法如何解決這個問題?或者我完全失去了,哈斯克爾以另一種方式做到了這一點?謝謝您的回答。
定義一個採用'IO String'參數的函數是錯誤的事情這裏。一個'IO字符串'不是一個包含在某些東西中的字符串,它是一個返回一個字符串的_procedure_。例如,綁定兩次將從網絡加載兩次。除非你正在編寫某種控制結構,否則通常不會編寫以'IO something'作爲參數的函數。我認爲如果你需要幫助編寫你想要調用的代碼,那就更好了。 – hammar
我真的只是哈斯克爾的初學者,說實話,我不喜歡它的懶惰。 我知道類似功能的行爲。我不喜歡對這個主題進行非常具體的描述,基本上我需要從Internet加載一個XML,對它進行處理並根據結果加載另一個XML。 但是,我確實想將任務分解爲更多的功能,因此我想使用IO輸入來實現這些方法(因爲大多數內部函數返回IO而我無法擺脫它)。那麼,最好有一個處理輸入的'do',包裝IO並正常調用其他函數? – Danstahr
是的。保持儘可能多的純代碼。這與工作和理解相比更容易,而且它還使得在解釋器中測試你的函數變得更加容易。 – hammar