无法匹配 foldl 内的元组
Can't match tuple inside of foldl
我有以下代码,它应该™ 将 excel 列类型转换为相应的数字。例如AA变成27,AB变成28:
import Data.Char (ord)
import Data.List (foldl1')
columnToNumber :: String -> Int
columnToNumber s = foldl1' (\acc (i, v) -> acc + 26 ^ i * v) (values s)
where values s = zip (reverse [0..(length s)]) ((\c -> ord c - 64) <$> s)
思路是把字符串"AA"转换成对应的数字
["A", "A"] -> [1, 1]
然后将其与底座一起压缩,从右到左 26^0、26^1、26^2 等等。
zip [1, 0] [1, 1] -> [(1, 1), (0, 1)]
这样折叠的结果就是
26^1 * 1 + 26^0 * 1 = 27
不幸的是,我收到以下错误,我不确定原因:
ExcelSheetColumn.hs:7:34:
Couldn't match expected type ‘Int’
with actual type ‘(Integer, Int)’
In the pattern: (i, v)
In the first argument of ‘foldl1'’, namely
‘(\ acc (i, v) -> acc + 26 ^ i * v)’
In the expression:
foldl1' (\ acc (i, v) -> acc + 26 ^ i * v) (values s)
ExcelSheetColumn.hs:7:63:
Couldn't match type ‘(Int, Int)’ with ‘Int’
Expected type: [Int]
Actual type: [(Int, Int)]
In the second argument of ‘foldl1'’, namely ‘(values s)’
In the expression:
foldl1' (\ acc (i, v) -> acc + 26 ^ i * v) (values s)
有人可以帮我吗?
要编译它,您实际上只需将 foldl1'
切换为 foldl'
并添加 starting 累加器:
import Data.Char (ord)
import Data.List (foldl')
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s)]) ((\c -> ord c - 64) <$> s)
如果您添加 Free_D
提出的建议(从 length s - 1
开始):
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s -1)]) ((\c -> ord c - 64) <$> s)
您得到了想要的结果:
λ> columnToNumber "AA"
27
λ> columnToNumber "AB"
28
我不知道你是否真的需要这个,但嘿,为什么不呢:
您可能不喜欢的是 columnToNumber "A1"
是 11
- 要解决此问题,您需要使用不同于字母的数字:
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s -1)]) (parse <$> s)
parse c
| c >= '0' && c <= '9' = ord c - ord '0'
| otherwise = ord c - 64
查看foldl1'
的定义,它必须取两个相同类型的东西并产生相似的东西
*Main Data.List> :t foldl1'
foldl1' :: (a -> a -> a) -> [a] -> a
但是foldl
是你想要的:
*Main Data.List> :t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
基本上是这样的:
import Data.Char (ord, toUpper)
columnToNumber :: String -> Int
columnToNumber s = foldl (\acc (i, v) -> acc + 26 ^ i * v) 0 $ values s where
values s = zip [l - 1, l - 2 ..0] ((\c -> (ord.toUpper) c - 64) <$> s) where
l = length s
我有以下代码,它应该™ 将 excel 列类型转换为相应的数字。例如AA变成27,AB变成28:
import Data.Char (ord)
import Data.List (foldl1')
columnToNumber :: String -> Int
columnToNumber s = foldl1' (\acc (i, v) -> acc + 26 ^ i * v) (values s)
where values s = zip (reverse [0..(length s)]) ((\c -> ord c - 64) <$> s)
思路是把字符串"AA"转换成对应的数字
["A", "A"] -> [1, 1]
然后将其与底座一起压缩,从右到左 26^0、26^1、26^2 等等。
zip [1, 0] [1, 1] -> [(1, 1), (0, 1)]
这样折叠的结果就是
26^1 * 1 + 26^0 * 1 = 27
不幸的是,我收到以下错误,我不确定原因:
ExcelSheetColumn.hs:7:34:
Couldn't match expected type ‘Int’
with actual type ‘(Integer, Int)’
In the pattern: (i, v)
In the first argument of ‘foldl1'’, namely
‘(\ acc (i, v) -> acc + 26 ^ i * v)’
In the expression:
foldl1' (\ acc (i, v) -> acc + 26 ^ i * v) (values s)
ExcelSheetColumn.hs:7:63:
Couldn't match type ‘(Int, Int)’ with ‘Int’
Expected type: [Int]
Actual type: [(Int, Int)]
In the second argument of ‘foldl1'’, namely ‘(values s)’
In the expression:
foldl1' (\ acc (i, v) -> acc + 26 ^ i * v) (values s)
有人可以帮我吗?
要编译它,您实际上只需将 foldl1'
切换为 foldl'
并添加 starting 累加器:
import Data.Char (ord)
import Data.List (foldl')
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s)]) ((\c -> ord c - 64) <$> s)
如果您添加 Free_D
提出的建议(从 length s - 1
开始):
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s -1)]) ((\c -> ord c - 64) <$> s)
您得到了想要的结果:
λ> columnToNumber "AA"
27
λ> columnToNumber "AB"
28
我不知道你是否真的需要这个,但嘿,为什么不呢:
您可能不喜欢的是 columnToNumber "A1"
是 11
- 要解决此问题,您需要使用不同于字母的数字:
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s -1)]) (parse <$> s)
parse c
| c >= '0' && c <= '9' = ord c - ord '0'
| otherwise = ord c - 64
查看foldl1'
的定义,它必须取两个相同类型的东西并产生相似的东西
*Main Data.List> :t foldl1'
foldl1' :: (a -> a -> a) -> [a] -> a
但是foldl
是你想要的:
*Main Data.List> :t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
基本上是这样的:
import Data.Char (ord, toUpper)
columnToNumber :: String -> Int
columnToNumber s = foldl (\acc (i, v) -> acc + 26 ^ i * v) 0 $ values s where
values s = zip [l - 1, l - 2 ..0] ((\c -> (ord.toUpper) c - 64) <$> s) where
l = length s