函数中的Haskell数组模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数中的Haskell数组模式相关的知识,希望对你有一定的参考价值。
嗨,总Haskell初学者:数组函数中的模式是什么样的?例如:我只想为我的数组中的第一个元素添加+1
> a = array (1,10) ((1,1) : [(i,( i * 2)) | i <- [2..10]])
我的第一个想法是:
> arraytest :: Array (Int,Int) Int -> Array (Int,Int) Int
> arraytest (array (mn,mx) (a,b):xs) = (array (mn,mx) (a,b+1):xs)
我希望你理解我的问题:)
您无法在数组上进行模式匹配,因为the data
declaration in the Data.Array.IArray
module for the Array
type没有公开任何数据构造函数。这是Haskell中的常见做法,因为它允许作者更新其数据类型的内部表示,而不会对其模块的用户进行重大更改。
因此,使用Array
的唯一方法是使用模块提供的功能。要访问数组中的第一个值,可以使用bounds
和(!)
的组合,或者从assocs
获取第一个键/值对。然后你可以使用(//)
来更新数组。
arraytest arr = arr // [(index, value + 1)]
where
index = fst (bounds arr)
value = arr ! index
如果您选择使用assocs
,则可以对其结果进行模式匹配:
arraytest arr = arr // [(index, value + 1)]
where
(index, value) = head (assocs arr) -- `head` will crash if the array is empty
或者您可以将Functor
实例用于列表和元组:
arraytest arr = arr // take 1 (fmap (fmap (+1)) (assocs arr))
但是,您可能会很快注意到array
包装缺少许多便利功能。与在其他语言中实现操作的方式相比,上述所有解决方案都相当冗长。
为了解决这个问题,我们有了lens
软件包(以及它的堂兄弟),它为Haskell添加了大量的便利功能,并使像array
这样的软件包更加可以忍受。这个包有一个相当陡峭的学习曲线,但它非常普遍使用,绝对值得学习。
import Control.Lens
arraytest arr = arr & ix (fst (bounds arr)) +~ 1
如果你眯着眼睛,你几乎可以看到它如何说arr[0] += 1
,但我们仍然没有牺牲不变性的任何好处。
这更像是对@ 4castle答案的延伸评论。你不能在Array
上模式匹配,因为它的实现是隐藏的;您必须使用其公共API来使用它们。但是,您可以使用公共API来定义此类模式(使用适当的语言扩展名):
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
-- PatternSynonyms: Define patterns without actually defining types
-- ViewPatterns: Construct patterns that apply functions as well as match subpatterns
import Control.Arrow((&&&)) -- solely to dodge an ugly lambda; inline if you wish
pattern Array :: Ix i => (i, i) -> [(i, e)] -> Array i e
-- the type signature hints that this is the array function but bidirectional
pattern Array bounds' assocs' <- ((bounds &&& assocs) -> (bounds', assocs'))
-- When matching against Array bounds' assocs', apply bounds &&& assocs to the
-- incoming array, and match the resulting tuple to (bounds', assocs')
where Array = array
-- Using Array in an expression is the same as just using array
arraytest (Array bs ((i,x):xs)) = Array bs ((i,x+1):xs)
我很确定来往[]
的转换使得这对于性能来说非常糟糕。
以上是关于函数中的Haskell数组模式的主要内容,如果未能解决你的问题,请参考以下文章