簡體   English   中英

在Haskell中無法將IO字符串轉換為[Char]

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

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