Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中是否有一种标准方法可以使用自定义匹配函数匹配两个列表?_Haskell - Fatal编程技术网

在Haskell中是否有一种标准方法可以使用自定义匹配函数匹配两个列表?

在Haskell中是否有一种标准方法可以使用自定义匹配函数匹配两个列表?,haskell,Haskell,我知道标准的方法是 (Eq z) => matchLists :: [x] -> [x] -> Bool matchLists xs ys = xs == ys 但我有一个特殊的元素匹配函数,它是从外部传递的,我无法控制它 所以我要找的是 matchLists :: (x -> x -> Bool) -> [x] -> [x] -> Bool (胡格尔说) 您最终会得到一个带有这样签名的自定义函数,还是会做些什么 编辑: zip函数不满足我的需

我知道标准的方法是

(Eq z) => matchLists :: [x] -> [x] -> Bool
matchLists xs ys = xs == ys
但我有一个特殊的元素匹配函数,它是从外部传递的,我无法控制它

所以我要找的是

matchLists :: (x -> x -> Bool) -> [x] -> [x] -> Bool
(胡格尔说)

您最终会得到一个带有这样签名的自定义函数,还是会做些什么

编辑:

zip函数不满足我的需要,因为结果列表的长度在2个输入列表中是最小的

编辑:

你觉得这个怎么样

--matchListsWith :: (a -> a -> Bool) -> [a] -> [a] -> Bool
matchListsWith :: (a -> b -> Bool) -> [a] -> [b] -> Bool
matchListsWith _ [] [] = True
matchListsWith _ (_:_) [] = False
matchListsWith _ [] (_:_) = False
matchListsWith matcher (x:xs) (y:ys) = matcher x y && matchListsWith matcher xs ys
一种可能性:

matchList f xs ys = and $ zipWith f xs ys
使用我们可以同时处理拉链和长度问题

matchWith :: (a -> b -> Bool) -> [a] -> [b] -> Bool
matchWith f as bs = and $ alignWith combiner as bs where
  combiner = these (const False) (const False) f
这将展开为与显式递归函数相同的代码,但使用
数据中的标记。这些标记用于标记各种列表对齐方式。如果您对
进行泛化,它还可以泛化到许多其他结构,如树或序列

matchWith :: (Foldable f, Align f) => (a -> b -> Bool) -> f a -> f b -> Bool
matchWith f as bs = Foldable.and $ alignWith combiner as bs where
  combiner = these (const False) (const False) f

data Tree a = Tip | Branch a (Tree a) (Tree a) deriving ( Functor, Foldable )

instance Align Tree where
  nil = Tip
  align Tip Tip = Tip
  align (Branch a la ra) Tip = Branch (This a) (fmap This la) (fmap This ra)
  align Tip (Branch b lb rb) = Branch (That b) (fmap That lb) (fmap That rb)
  align (Branch a la ra) (Branch b lb rb) =
    Branch (These a b) (align la lb) (align ra rb)
所以我们有

λ> matchWith (==) Tip Tip
True
λ> matchWith (==) (Branch 3 Tip Tip) (Branch 3 Tip Tip)
True
λ> matchWith (==) (Branch 3 Tip Tip) (Branch 3 Tip (Branch 3 Tip Tip))
False
(不妨…)


我认为手写的方法在这里非常好。如果您还没有使用某个库,而该库恰好具有解决此问题的合适函数,那么我认为,仅仅为了减少三行代码而添加另一个依赖项是不值得的

不过,您仍然可以删除一行:

matchListWith :: (a -> b -> Bool) -> [a] -> [b] -> Bool
matchListWith f (x:xs) (y:ys) = f x y && matchListWith f xs ys
matchListWith _ []     []     = True
matchListWith _ _      _      = False

如果列表的长度不同,这可能会导致令人惊讶的行为
和$zipWith(=)[1][1,2]
的计算结果为
True
。我也是这么想的。我不希望这是真的。所以我想我需要继续寻找。没有理由不使用更通用的类型
(a->b->Bool)->[a]->[b]->Bool
@Cirdec,这是一个很好的观点
matchListWith :: (a -> b -> Bool) -> [a] -> [b] -> Bool
matchListWith f (x:xs) (y:ys) = f x y && matchListWith f xs ys
matchListWith _ []     []     = True
matchListWith _ _      _      = False