![](/img/trans.png)
[英]Haskell IO return Couldn't match type ‘[Char]’ with ‘Char’ Expected type: String Actual type: [String]
[英]Couldn't convert an IO String to [Char] in Haskell
我編寫了一個簡單的函數,該函數具有兩個文件名(字符串),並將第一個文件的內容寫入第二個文件,並將第二個文件應用於每個字符的toUpper
。
import Data.Char
ioFile f1 f2 = do
s <- readFile f1
sUp <- [toUpper c | c <- s]
writeFile f2 sUp
但是口譯員提出了一個錯誤
Couldn't match expected type ‘IO String’ with actual type ‘[Char]’
In a stmt of a 'do' block: sUp <- [toUpper c | c <- s]
In the expression:
do { s <- readFile f1;
sUp <- [toUpper c | c <- s];
writeFile f2 sUp }
In an equation for ‘ioFile’:
ioFile f1 f2
= do { s <- readFile f1;
sUp <- [toUpper c | c <- s];
writeFile f2 sUp }
如何使用s
作為[Char]
而不是IO String
?
您不能綁定sUp <- [toUpper c | c <- s]
sUp <- [toUpper c | c <- s]
這樣。 請注意,與接受的答案所建議的不同,這並不意味着您不能給它起一個名字。 首先,有一個return
函數可以為IO
(或任何monad,但現在我們在IO
)提供純值,因此sUp <- return [toUpper c | c <- s]
sUp <- return [toUpper c | c <- s]
確實有效。 還有let語法的一種變體,可以做到這一點: let sUp = [toUpper c | c <- s]
let sUp = [toUpper c | c <- s]
。
第二行不是IO Monadic操作,它只是列表理解,因此您應將其編寫為:
import Data.Char
ioFile f1 f2 = do
s <- readFile f1
writeFile f2 [toUpper c | c <- s]
但是,Haskell社區的很大一部分認為do
有害 ,因此希望看到:
ioFile f1 f2 = readFile f1 >>= \s -> writeFile f2 $ map toUpper s
甚至更短:
ioFile f1 f2 = readFile f1 >>= writeFile f2 . map toUpper
使用map :: (a -> b) -> [a] -> [b]
toUpper
map :: (a -> b) -> [a] -> [b]
您可以將給定函數(在本例中為toUpper
)應用於給定列表的每個元素,並生成結果列表。 (>>=) :: Monad m => ma -> (a -> mb) -> mb
非正式地等同於在左monad的“結果”上調用給定的右操作數函數。 所以c >>= f
等於:
do
x <- c
f x
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.