2014-11-23 72 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

相关问题