向量上的Haskell模式匹配



是否可以在向量上使用列表样式的模式匹配?

import qualified Data.Vector as V
f :: V.Vector a -> a
f (x:xs) = x 

给出错误

-XViewPatterns可以让您这样做:

{-# LANGUAGE ViewPatterns #-}
module VecViewPats where
import Data.Vector (Vector)
import qualified Data.Vector as V
uncons :: Vector a -> Maybe (a, Vector a)
uncons v = if V.null v
  then Nothing
  else Just (V.unsafeHead v, V.unsafeTail v)
vsum :: Num a => Vector a -> a
vsum (uncons -> Just (a,av)) = a + vsum av
vsum (uncons -> Nothing) = 0

-XLambdaCase

import Control.Category ((>>>))
-- ...
vsum :: Num a => Vector a -> a
vsum = uncons >>> case
  Just (a,av) -> a + vsum av
  Nothing     -> 0

但老实说,当你使用一个数据结构(Vector)作为另一个([])时,这似乎有点代码味,这表明你可能对数据结构的选择是错误的

如果你真的只是想把它当作一个列表来处理某些算法,为什么不使用toList呢?

@Cactus已经指出-XPatternSynonym(在7.8中引入)与-XViewPattern相结合可以用于向量上的模式匹配。我在这里是想进一步扩大他的评论。

pattern Empty <- (V.null -> True) 

上面为空向量定义了一个模式同义词EmptyEmpty模式使用视图模式(V.null -> True)与空向量匹配。然而,它不能在其他地方用作表达式,即单向同义词,因为系统并不真正知道Empty作为向量是什么(我们只知道null vTrue,但也可能有其他向量给出True)。

为了解决这个问题,可以添加where子句,指定Empty实际上是一个空向量,即双向同义词,以及类型签名:

pattern Empty :: Vector a
pattern Empty <- (V.null -> True) where Empty = V.empty 

这个模式同义词可以用来定义uncons,而不需要if表达式:

uncons :: Vector a -> Maybe (a, Vector a)
uncons Empty = Nothing
uncons v     = Just (unsafeHead v, unsafeTail v)

我们使用uncons来定义单向同义词。注意,由于cons对于vector:来说代价高昂,所以我不将其设为双向

pattern (:<|)  :: a -> Vector a -> Vector a
pattern x :<| xs <- (uncons -> Just (x, xs))

无论如何,我们终于能够像列表一样在向量上进行模式匹配:

vsum :: Num a => Vector a -> a 
vsum Empty = 0
vsum (x :<| xs) = x + vsum xs

完整的代码在这里。

Vectors不是用于那种模式匹配的——它们的创建是为了提供Haskell O(1)列表,或者可以从任何点高效访问的列表。

最接近你写的东西是这样的:

f v = V.head v

或者,如果您正在寻找递归,tail函数将获得列表的其余部分。

但是,如果你试图做一些沿着这样的列表移动的事情,那么有foldlfindmap等函数的Vector等价物。这取决于你打算做什么。

相关内容

  • 没有找到相关文章

最新更新