List Haskell模式匹配难题

List Haskell模式匹配难题,list,haskell,pattern-matching,prepend,List,Haskell,Pattern Matching,Prepend,我试图在一个可能包含未定义元素$的对列表中的任意位置进行搜索。我只想搜索该特殊元素前面的列表部分,因此我尝试了类似这样的方法。我们打算将元素n和列表x作为参数: checkNotSameScope :: Env -> VarName -> Expr -> Expr checkNotSameScope (xs:("$", Undefined):_) n e = if alreadyThere n xs then BoolLit False

我试图在一个可能包含未定义元素$的对列表中的任意位置进行搜索。我只想搜索该特殊元素前面的列表部分,因此我尝试了类似这样的方法。我们打算将元素n和列表x作为参数:

checkNotSameScope :: Env -> VarName -> Expr -> Expr
checkNotSameScope (xs:("$", Undefined):_) n e = if alreadyThere n xs then BoolLit False
                                                   else BoolLit True

但这是行不通的;编译器似乎指示xs:。。仅处理列表前面的单个值。我不能使用:来指示列表的第一个块;只有一个元素。回顾过去,这是有道理的;否则,编译器如何知道该做什么?在像x这样的东西上添加一个s并不能神奇地生成多个元素!但是我如何才能解决这个问题呢

不幸的是,即使使用智能编译器和语言,也无法避免某些编程

在您的例子中,似乎您希望列表的一部分包含一个特定的元素。一般来说,要查找符合某种条件的列表,可以使用标准库takeWhile函数。然后您可以在上面运行alreadyThere:


对于不出现$,Undefined的列表,这可能不是您想要的,因此请小心。

不幸的是,即使使用智能编译器和语言,也无法避免某些编程

在您的例子中,似乎您希望列表的一部分包含一个特定的元素。一般来说,要查找符合某种条件的列表,可以使用标准库takeWhile函数。然后您可以在上面运行alreadyThere:


这可能不是您想要的列表,其中未定义的$不会出现,因此请注意。

与Joachim的答案类似,您可以使用,这将允许您在必要时检测未定义的$何时不会出现。i、 e

checkNotSameScope xs n e = case break (== ("$", Undefined)) xs of
                             (_, [])  -> .. -- ("$", Undefined) didn't occur!
                             (xs', _) -> BoolLit . not $ alreadyThere n xs'

注意。在这个解决方案中,您会失去一些惰性,因为必须遍历列表直到$,Undefined,或者直到最后,才能检查第一个案例。

与Joachim的答案类似,您可以使用,这将允许您在必要时检测$,Undefined何时没有发生。i、 e

checkNotSameScope xs n e = case break (== ("$", Undefined)) xs of
                             (_, [])  -> .. -- ("$", Undefined) didn't occur!
                             (xs', _) -> BoolLit . not $ alreadyThere n xs'

注意。在这个解决方案中,您会失去一些惰性,因为必须遍历列表直到$,Undefined,或者直到最后,才能检查第一个案例。

Haskell无法进行这种开箱即用的模式匹配,尽管有些语言可以使用,例如,或F

但是我们可以使用Haskell现有的模式匹配功能来获得类似的结果。让我们首先定义一个名为deconstruct的函数,定义如下:

deconstruct :: [a] -> [([a], a, [a])]
deconstruct [] = []
deconstruct [x] = [([], x, [])]
deconstruct (x:xs) = ([], x, xs) : [(x:ys1, y, ys2) | (ys1, y, ys2) <- deconstruct xs]
使用此选项,您可以按如下方式定义函数:

checkNotSameScope xs n e =
    case [ys | (ys, ("$", Undefined), _) <- deconstruct xs] of
        [ys] -> BoolLit $ not $ alreadyThere n xs
        _    -> -- handle the case when ("$", Undefined) doesn't occur at all or more than once
我们可以使用获取更接近您所需的内容:

checkNotSameScope xs n e = BoolLit $ not $ any (alreadyThere n) prefixes
    where
        prefixes = do
            (xs, ("$", Undefined), _) <- deconstruct xs
            return xs

这里发生了几件事。首先,prefixes变量将存储在$之前的所有前缀列表,未定义对-或者如果该对不在输入列表xs中,则无前缀列表。然后使用函数检查alreadyThere n是否为任何前缀提供True。剩下的就是完成函数的逻辑。

Haskell无法进行这种开箱即用的模式匹配,尽管有些语言可以使用,例如,F或

但是我们可以使用Haskell现有的模式匹配功能来获得类似的结果。让我们首先定义一个名为deconstruct的函数,定义如下:

deconstruct :: [a] -> [([a], a, [a])]
deconstruct [] = []
deconstruct [x] = [([], x, [])]
deconstruct (x:xs) = ([], x, xs) : [(x:ys1, y, ys2) | (ys1, y, ys2) <- deconstruct xs]
使用此选项,您可以按如下方式定义函数:

checkNotSameScope xs n e =
    case [ys | (ys, ("$", Undefined), _) <- deconstruct xs] of
        [ys] -> BoolLit $ not $ alreadyThere n xs
        _    -> -- handle the case when ("$", Undefined) doesn't occur at all or more than once
我们可以使用获取更接近您所需的内容:

checkNotSameScope xs n e = BoolLit $ not $ any (alreadyThere n) prefixes
    where
        prefixes = do
            (xs, ("$", Undefined), _) <- deconstruct xs
            return xs

这里发生了几件事。首先,prefixes变量将存储在$之前的所有前缀列表,未定义对-或者如果该对不在输入列表xs中,则无前缀列表。然后使用函数检查alreadyThere n是否为任何前缀提供True。剩下的就是完成函数的逻辑。

也许我应该问,如果没有模式匹配,我怎么能用另一种方法来完成呢,因为这是不可能的?Haskell是为非常聪明的人设计的。也许我应该问一下,如果没有模式匹配,我怎么能用另一种方式来做呢?因为这是不可能的?Haskell是为非常聪明的人设计的,甚至可以是checkNotSameScope xs n e=BoolLit。不早就有了。takeWhile/=$,未定义$xsRight。我只是修复了有问题的代码,没有阅读太多其他代码,甚至没有检查notsamescope xs n e=BoolLit。不早就有了。takeWhile/=$,未定义$xsRight。我只是修改了有问题的代码,没有读太多其他的。谢谢!通常情况下,正确的答案是完全不被欣赏的。因此,它被打破了。它的投票系统是双层的。这看起来好像是一个知识管理系统,它本身就是这样,但事实并非如此。谢谢!通常情况下,正确的答案是完全不被欣赏的。因此,它被打破了。它的投票系统是双层的。看起来,知识管理系统似乎也是如此,它本身就是这样,但事实并非如此。