2014-11-23 75 views
0

我正在寫一個函數來將字符串列表(從CSV文件讀取)轉換爲雙精度列表。它在第三行給我一個錯誤。將[String]列表轉換爲Haskell中的[Double]列表

stringToDouble :: [String] -> [Double] 
stringToDouble [] = error "empty list" 
stringToDouble [x] = read x :: Double -- the `read` gives me an error 
stringToDouble (x:xs) = stringToDouble xs 

是否因爲我沒有將轉換後的Double放入需要返回的列表中?

回答

8

錯誤來自於read x類型爲Double而不是[Double],但是就其本身而言,即使使用該修補程序,您的功能也無法正常工作。

讓我們把你的函數放到單詞中:「把字符串列表的前面的元素作爲一個double來讀取,然後對列表的其餘部分做同樣的處理」。現在讓我們來看看你的功能:

stringToDouble :: [String] -> [Double] 
stringToDouble [] = error "empty list" 
stringToDouble [x] = read x :: Double -- Error 
stringToDouble (x:xs) = stringToDouble xs 

現在讓我們將修復應用到它。另外,沒有理由在空列表中出錯。只是產量和空的雙打名單:

stringToDouble :: [String] -> [Double] 
stringToDouble [] = [] 
stringToDouble [x] = [read x :: Double] -- Put the single value into a list 
stringToDouble (x:xs) = stringToDouble xs 

問題在於遞歸步驟。在列表上調用stringToDouble與在列表的尾部調用stringToDouble相同。第一個元素簡單地被丟棄。您想要轉換頭並將其放回列表中。

stringToDouble :: [String] -> [Double] 
stringToDouble [] = [] 
stringToDouble [x] = [read x :: Double] -- Put the single value into a list 
stringToDouble (x:xs) = (read x :: Double) : stringToDouble xs 

哪裏(:)是用於將元件連接到列表中的正面的操作員。因此,甚至不需要中間線,因爲遞歸步驟將處理轉換,空列表步驟將處理停止條件。

stringToDouble :: [String] -> [Double] 
stringToDouble [] = [] 
stringToDouble (x:xs) = (read x :: Double) : stringToDouble xs 

現在,實事求是,你可以可能刪除:: Double部分和Haskell會找出你的意思與功能的類型約束,但它不會傷害,有時它有助於可讀性離開它英寸

+0

非常感謝您的支持。你有什麼建議,如果我有這樣的列表'[「a」,「1.2」]'..我怎樣才能使用數字而不是單詞,以便「a」會被忽略?通過正則表達式可能? – letsjak 2014-11-23 23:50:58

+0

你是什麼意思「被忽略」?你想要發生什麼事情,非數字?你不能在Haskell中有一個異類列表,所以你不能有[「a」,1.2],因爲它沒有有效的類型。 – 2014-11-24 00:49:02

+4

如果意圖忽略無法讀取的值,則定義'readMaybe x = {[(y,「」)] - >只是y; _ - > Nothing}'和'stringToDouble = catMaybes。地圖readMaybe' – user2407038 2014-11-24 01:12:16

1

你是對的 - read x :: DoubleDouble類型,而函數的返回類型是[Double](意思是「Double」的列表)。

事情是這樣的:

stringToDouble [x] = [read x :: Double] 

應該工作。

請注意,如果您嘗試單獨轉換列表中的每個元素,則應該使用map而不是使用顯式遞歸來編寫函數。如果fString -> Double類型,則map f將是[String] -> [Double]類型的函數。

+0

如果我這樣做,它只打印第一個元素。 'stringToDouble(x:xs)= stringToDouble xs'沒有得到執行 – letsjak 2014-11-23 23:37:48

+1

你的當前函數只對列表的最後一個元素調用'read':如果一個列表有多個項目,它會忽略第一個元素。也許你的意思是像第三種情況下的'stringToDouble(x:xs)= read x:stringToDouble xs'? – Benesh 2014-11-23 23:39:14

+0

@letsjak它會執行(對於包含多個元素的列表),但它所做的只是在尾部進行遞歸。 – sepp2k 2014-11-23 23:40:41

相關問題