在我的小程序中解析模式错误
Parse error in pattern in my little program
left :: [String]->[Char]->Char
left [] _ = []
left (x:xs) (head xs) = x -- it says error at head
我使用了正确的括号,但仍然采用解析 error.By 的方式,我试图获取列表中的前一个元素,例如 [["A"],["B"],["C"],["D"],["E"]]
。也许我还有其他错误。请纠正我。
第二个问题是如何选取前一个元素的前一个索引字符。比如给函数这个列表 [["J","O","H","N"],["A","L","I","C","E"]] 和 "C" ,我希望得到 "H"。我的意思是 "C" 是第二个元素的第四个索引,而 "H" 是前一个元素的第三个索引。提前致谢
要访问 "previous" 列表元素,您必须使用不同的递归。例如
foo [] = baseCase
foo [x] = onlyOneElement x
foo (x1:x2:xs) = use x1 x2 (foo (x2:xs))
调用 foo [1,2,3,4,5]
时,您可以访问 x1=1, x2=2
。递归时,您将获得 x1=2, x2=3
的访问权限,依此类推。因此,您可以认为 x2
是 "current" 元素,而 x1
是前一个元素。
如果我理解得很好,您需要一个函数来查找 String
列表中的字符,以及 return 前面索引处前面字符串的字符。
类似于:
f ["JOHN", "ALICE"] 'C' == 'H'
首先你需要知道 Char
字面量在 Haskell 中用单引号分隔('A'
),而 String
字面量用双引号分隔("ABC"
).
由于在Haskell中String
是[Char]
的别名,"ABC"
等同于['A', 'B', 'C']
。
也就是说,在 Haskell 中你不能定义这样的函数:f a a = stuff
。 GHC 会抱怨 a
被定义了多次。
所以要检查两个参数是否有一些 属性,你需要 guard patterns.
所以我会这样写你的第一个函数:
left :: [String] -> String -> String
left [] _ = ""
left [x] _ = ""
left (x1:x2:xs) str
| x2 == str = x1
| otherwise = left (x2:xs) str
关于你的第二个问题:
import Data.List
f :: [String] -> Char -> Maybe Char
f [] _ = Nothing
f [a] _ = Nothing
f (x1:x2:xs) c
| Just i <- elemIndex c x2 = Just $ x1 !! (i-1)
| otherwise = f (x2:xs) c
备注:
left
也应该 return 一个 Maybe String
以防 str
找不到或第一个出现。
f
不检查 x1
是否真的足够长
- 通常在Haskell中,列表参数在最后,以允许currying。
编辑:
使用 zip
的更聪明的方法(在模块 Data.List
中)。
f :: [String] -> Char -> Maybe Char
f [] _ = Nothing
f [_] _ = Nothing
f (x1:"":xs) c = f xs c
f (x1:x2:xs) c = f' (zip x1 (tail x2))
where f' [] = f (x2:xs) c
f' ((a,b):l) = if b == c then a else f' l
这个版本不会崩溃。它会return第一个满足"being mth character in nth string, while the (m+1)th character in (n+1)th string"的字符是c
。结果将包装在 Maybe
(Just 'H'
) 中。否则,它 returns Nothing
(Maybe
大致是 Haskell 的可空类型)。
zip
是一个将两个列表合并成一对列表的函数:
zip ['a', 'b', 'c'] [1, 2] == [('a', 1), ('b', 2)]
结果列表的大小是最小的。所以在这个例子中,发生的是:
zip "JOHN" (tail "ALICE") == [('J','L'), ('O', 'I'), ('H', 'C'), ('N', 'E')]
然后您只需检查第二个字符是否是搜索到的字符,然后 return 这对字符中的第一个字符。
left :: [String]->[Char]->Char
left [] _ = []
left (x:xs) (head xs) = x -- it says error at head
我使用了正确的括号,但仍然采用解析 error.By 的方式,我试图获取列表中的前一个元素,例如 [["A"],["B"],["C"],["D"],["E"]]
。也许我还有其他错误。请纠正我。
第二个问题是如何选取前一个元素的前一个索引字符。比如给函数这个列表 [["J","O","H","N"],["A","L","I","C","E"]] 和 "C" ,我希望得到 "H"。我的意思是 "C" 是第二个元素的第四个索引,而 "H" 是前一个元素的第三个索引。提前致谢
要访问 "previous" 列表元素,您必须使用不同的递归。例如
foo [] = baseCase
foo [x] = onlyOneElement x
foo (x1:x2:xs) = use x1 x2 (foo (x2:xs))
调用 foo [1,2,3,4,5]
时,您可以访问 x1=1, x2=2
。递归时,您将获得 x1=2, x2=3
的访问权限,依此类推。因此,您可以认为 x2
是 "current" 元素,而 x1
是前一个元素。
如果我理解得很好,您需要一个函数来查找 String
列表中的字符,以及 return 前面索引处前面字符串的字符。
类似于:
f ["JOHN", "ALICE"] 'C' == 'H'
首先你需要知道 Char
字面量在 Haskell 中用单引号分隔('A'
),而 String
字面量用双引号分隔("ABC"
).
由于在Haskell中String
是[Char]
的别名,"ABC"
等同于['A', 'B', 'C']
。
也就是说,在 Haskell 中你不能定义这样的函数:f a a = stuff
。 GHC 会抱怨 a
被定义了多次。
所以要检查两个参数是否有一些 属性,你需要 guard patterns.
所以我会这样写你的第一个函数:
left :: [String] -> String -> String
left [] _ = ""
left [x] _ = ""
left (x1:x2:xs) str
| x2 == str = x1
| otherwise = left (x2:xs) str
关于你的第二个问题:
import Data.List
f :: [String] -> Char -> Maybe Char
f [] _ = Nothing
f [a] _ = Nothing
f (x1:x2:xs) c
| Just i <- elemIndex c x2 = Just $ x1 !! (i-1)
| otherwise = f (x2:xs) c
备注:
left
也应该 return 一个Maybe String
以防str
找不到或第一个出现。f
不检查x1
是否真的足够长- 通常在Haskell中,列表参数在最后,以允许currying。
编辑:
使用 zip
的更聪明的方法(在模块 Data.List
中)。
f :: [String] -> Char -> Maybe Char
f [] _ = Nothing
f [_] _ = Nothing
f (x1:"":xs) c = f xs c
f (x1:x2:xs) c = f' (zip x1 (tail x2))
where f' [] = f (x2:xs) c
f' ((a,b):l) = if b == c then a else f' l
这个版本不会崩溃。它会return第一个满足"being mth character in nth string, while the (m+1)th character in (n+1)th string"的字符是c
。结果将包装在 Maybe
(Just 'H'
) 中。否则,它 returns Nothing
(Maybe
大致是 Haskell 的可空类型)。
zip
是一个将两个列表合并成一对列表的函数:
zip ['a', 'b', 'c'] [1, 2] == [('a', 1), ('b', 2)]
结果列表的大小是最小的。所以在这个例子中,发生的是:
zip "JOHN" (tail "ALICE") == [('J','L'), ('O', 'I'), ('H', 'C'), ('N', 'E')]
然后您只需检查第二个字符是否是搜索到的字符,然后 return 这对字符中的第一个字符。