Haskell模式匹配向量

时间:2016-05-03 00:54:27

标签: haskell vector pattern-synonyms

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

import qualified Data.Vector as V

f :: V.Vector a -> a
f (x:xs) = x 

给出错误

3 个答案:

答案 0 :(得分:7)

-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

答案 1 :(得分:1)

向量并不适用于那种模式匹配 - 它们是为了给Haskell O(1)列表或可以从任何点有效访问的列表而创建的。

与你所写的最接近的是这样的事情:

f v = V.head v

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

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

答案 2 :(得分:1)

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

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

上面为空向量定义了模式同义词EmptyEmpty模式使用视图模式(V.null -> True)与空向量匹配。但是,它不能在其他地方用作表达式,即 uni 方向的同义词,因为系统实际上不知道Empty作为向量是什么(我们只知道{{ 1}}是null v,但也可能有其他向量也提供True

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

where

此模式同义词可用于定义pattern Empty :: Vector a pattern Empty <- (V.null -> True) where Empty = V.empty 而不使用if表达式:

uncons

我们使用uncons :: Vector a -> Maybe (a, Vector a) uncons Empty = Nothing uncons v = Just (unsafeHead v, unsafeTail v) 来定义单向同义词。请注意,由于uncons对于矢量而言代价高昂,因此我不会将其设为双向:

cons

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

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

完整的代码是here