Haskell 如何根据列表的后半部分简洁地匹配列表,并将其绑定';那么前一半是什么?

Haskell 如何根据列表的后半部分简洁地匹配列表,并将其绑定';那么前一半是什么?,haskell,Haskell,假设我有一个函数f::String->String,想要匹配表单的参数 _ ++ "bar" 其中,\u是我要返回的未指定字符串。换句话说,我想匹配像foobar和bazbar这样的参数,并分别返回foo和baz 使用ViewPatterns可以实现如下操作: {-# LANGUAGE ViewPatterns #-} f :: String -> String f x@(reverse . take 3 $ reverse -> "bar") = take (n-3) x

假设我有一个函数
f::String->String
,想要匹配表单的参数

_ ++ "bar"
其中,
\u
是我要返回的未指定字符串。换句话说,我想匹配像
foobar
bazbar
这样的参数,并分别返回
foo
baz

使用
ViewPatterns
可以实现如下操作:

{-# LANGUAGE ViewPatterns #-}

f :: String -> String
f x@(reverse . take 3 $ reverse -> "bar") = take (n-3) x
    where n = length x
…但这远不是理想的。主要是因为如果我决定结合两个或更多这样的模式,事情会很快变得多毛

理想情况下,我希望能够写出这样的内容:

f (x:"bar") = x
但不幸的是,这是无效的哈斯克尔


ViewPatterns或其他扩展中是否有适当的解决方案?

不要使用模式匹配。模式匹配通常比较便宜,并且匹配输入数据的结构。这是一个非常昂贵的模式,编写时似乎计算起来非常便宜。如果您想这样做,请将其作为一个guard子句编写,这样您就可以清楚地知道发生了什么。

在内置的
字符串上,这是一个非常糟糕的主意,因为您的模式匹配结果非常昂贵。在其他字符串类型上,如
Text
ByteString
,可以使用模式保护:

{-#语言重载字符串}
导入符合条件的数据。文本为T
f::文本->文本
f x |仅x'文本
f(T.stripSuffix“bar”->仅x’=。。。
stripSuffix::(等式a)=>[a]->[a]->[a]->可能[a]
stripSuffix针=下降(长度针)
哪里
去xs[]=如果xs==针,那么就去[]其他什么都没有
go(x:xs)(x:ys)=(x:)go-xs-ys
f(条带后缀“bar”->仅优先)=优先
我没有对它进行过太多的测试,但这是一个简单的解决方案,不会带来额外的正则表达式/解析器。

这在TemplateHaskell中几乎是可能的-有经验的人可以改进这个答案

import Language.Haskell.TH
导入语言.Haskell.TH.Syntax
(+++)::Q Pat->String->Q Pat
x+++y=[p |((\string->splitAt(length string-length y)string)->(x,$literal_模式))|]
其中,literal_pattern=returnQ(LitP(StringL-y))
这在模式位置可用,您可以使用TemplateHaskell的quasiquoting将模式作为第一个参数传入:

f$([p | x |]+++“bar”)=x

令人恼火的是,对于如何将模式传递给TemplateHaskell拼接,我找不到比这更简洁的解释。

正则表达式如何?它们可以包含结束字符串锚,您可以只匹配初始段,例如“(*)bar$”我不知道Haskell中的正则表达式。那会是什么样子?也许是时候写一个真正的解析器了。(我打赌你问这个问题是因为它是一段更大的代码的一部分,实际上正在进行解析。)打开一个窗口了解这个问题的深度:什么是
f(x++y)=(x,y)
compute?我认为,当问题对性能没有任何兴趣时,出于性能原因建议不要做某些事情是错误的-过早的优化是万恶之源。请随意做你想做的事情。我的答案是建议你完全做那些慢的事情……但是在一个守卫中做,你可以看到它们很昂贵。当性能还不是问题时,这仍然是在考虑性能编码——谁在乎这很昂贵?你甚至不知道这段代码是否会以某种方式被共享,这意味着阅读它的人不知道“模式匹配”的行为。我建议不要将TH用于像这样的琐碎任务。除了损害可读性之外,它还影响编译时间。另外,您的
++
完全错误-它忘记检查后缀是否匹配!与命中非穷举案例错误不同,
f“hello”
愉快地返回
“he”
。这是因为
ViewPatterns
引入了一个新的
y
变量,而不是断言它等于您的外部
y
。在我看来,这个解决方案的复杂性超过了小的语法优势。谢谢你指出这一点-我对准量化机制有点幼稚。更新后的版本有效。但我不认为可读性或编译时间足够重要,可以忽略这些类型的解决方案,除非询问的人这么说。问题是关于句法上的好处——这就是我想要回答的。
stripSuffix :: (Eq a) => [a] -> [a] -> Maybe [a]
stripSuffix needle = go <*> drop (length needle)
  where
    go xs [] = if xs == needle then Just [] else Nothing
    go (x:xs) (_:ys) = (x:) <$> go xs ys

f (stripSuffix "bar" -> Just pref) = pref