是否可以在“以f
开头”,然后是任何文字,以“以b
结尾?”模式匹配?
我试过了:
f :: String -> Bool
f ('f':xs:'b') = True
f _ = False
但我收到了一个错误:
explore/PatternMatching.hs:2:11:
Couldn't match expected type ‘[Char]’ with actual type ‘Char’
In the pattern: 'b'
In the pattern: xs : 'b'
In the pattern: 'f' : xs : 'b'
Failed, modules loaded: none.
答案 0 :(得分:7)
没有模式匹配语言扩展,没有简单的方法可以做到这一点。我会把它写成:
f :: String -> Bool
f str = case (take 1 str, drop (length str - 1) str) of
("f", "b") -> True
otherwise -> False
(使用take
和drop
以避免在使用例如head
或!!
时特别处理可能导致错误的空字符串的情况
Prelude> f "flub"
True
Prelude> f "foo"
False
Prelude> f "fb"
True
Prelude> f "fbbbb"
True
Prelude> f "fbbbbf"
False
Prelude> f ""
False
答案 1 :(得分:2)
正如先前的答案所述,没有办法直接为此进行模式匹配。人们可以按如下方式实现它:
f 'f':xs@(_:_) = last xs == 'b' -- @(_:_) ensures nonempty tail
f _ = False
答案 2 :(得分:1)
不,不可能直接。
:
想要左侧的列表元素和右侧的列表。
'f':xs:'b'
无效,因为第二个:
右侧的内容不是列表。
'f':xs:"b"
有效,但不会做你想做的事,因为xs
被推断为列表元素,而不是列表。
我会这样做:
f s = f' (s, reverse s) where
f' ('f':_, 'b':_) = True
f' _ = False
测试:
*Main> f ""
False
*Main> f "f"
False
*Main> f "b"
False
*Main> f "fb"
True
*Main> f "feeeeeeeb"
True
*Main> f (repeat 'b')
False
*Main> f (repeat 'f')
(hangs indefinitely)
答案 3 :(得分:1)
对于类似列表的数据结构,允许您在常量时间中访问其第一个和最后一个元素,您可能需要查看Hinze和Paterson的指尖。
它们由例如containers和here are the relevant views解构它们。如果您经常使用这种模式,您可能想要编写自己的视图,将左侧和右侧的解构结合起来:
data ViewLR a = EmptyLR | SingleLR a | BothSides a (Seq a) a
viewlr :: Seq a -> ViewLR a
viewlr seq =
case viewl seq of
EmptyL -> EmptyLR
hd :< rest ->
case viewr rest of
EmptyR -> SingleLR hd
middle :> tl -> BothSides hd middle tl
您可能还希望阅读View Patterns,以便能够在左侧“模式匹配”,而不必使用case ... of
。
答案 4 :(得分:0)
定义专用的String
数据类型,从而形成模式匹配,例如考虑
data HString = Ends Char Char | Plain String
deriving (Show, Eq)
因此
f :: HString -> Bool
f (Ends h l) = (h,l) == ('f','b')
f (Plain "") = False
f (Plain xs) = f $ Ends (head xs) (last xs)
等等
*Main> f (Plain "")
False
*Main> f (Plain "fabs")
False
*Main> f (Plain "fab")
True
<强>更新强>
同样,考虑使用中缀运算符:-:
来表示构造函数,例如
infixr 5 :-:
data HString = Char :-: Char | Plain String
deriving (Show, Eq)
因此
f :: HString -> Bool
f (h :-: l) = (h,l) == ('f','b')
f (Plain "") = False
f (Plain xs) = f $ (head xs) :-: (last xs)
答案 5 :(得分:0)
要了解错误,只需检查签名:operator
Prelude> :t (:)
(:) :: a -> [a] -> [a]
它可以接受一个元素和一个列表来给出附加列表。当你提供'f':xs:'b'时,它与函数调用不匹配。