我有如下数据结构:
import qualified Data.Vector.Unboxed as V
mylist :: [V.Vector (Int, Int)]
我需要搜索这个向量列表以查找满足谓词的元素。该算法保证我会找到该元素。
到目前为止,我有这样的事情:
go [] = error "Could not find"
go pred (p:ps) =
case V.find pred p of
Just a -> a
Nothing -> go ps
这很简单,但我想摆脱递归。是否有一种结构可以让我“摆脱”#34;递归?
答案 0 :(得分:5)
使用newtype包,可以方便地编写
import Control.Newtype
import Data.Monoid
import Data.Foldable
go :: Foldable f => (a -> Maybe b) -> f a -> Maybe b
go = ala' First foldMap
我认为很好地暴露了你在这个计算中使用的结构。
答案 1 :(得分:2)
在某些时候使用了递归,但您可以使用Data.Monoid
和map
简化此操作:
go :: (a -> Bool) -> [V.Vector a] -> Maybe a
go pred = getFirst . mconcat . map (First . V.find pred)
我建议将其保留为返回Maybe a
而不是使用error
,大多数人会建议不要使用error
,因为它只会导致您的程序崩溃,而不是让您优雅地退出
您可以使用Data.Maybe
函数实现此方法:
go pred = listToMaybe . catMaybes . map (V.find pred)
或者
go pred = listToMaybe . mapMaybe (V.find pred)
或者您可以MonadPlus
使用Maybe
实例(首先导入Control.Monad
):
go pred = msum . map (V.find pred)
或Alternative
中的Control.Applicative
个实例:
go pred = foldr (<|>) empty . map (V.find pred)
-- Or using foldl if you really want to
有很多方法可以解决这个问题。