Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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
Arrays 函数中的Haskell数组模式_Arrays_Haskell_Pattern Matching - Fatal编程技术网

Arrays 函数中的Haskell数组模式

Arrays 函数中的Haskell数组模式,arrays,haskell,pattern-matching,Arrays,Haskell,Pattern Matching,Hi total Haskell初学者:数组函数中的模式是什么样的?例如:我只想向数组中的第一个元素添加+1 > a = array (1,10) ((1,1) : [(i,( i * 2)) | i <- [2..10]]) 我希望您理解我的问题:)您无法在阵列上进行模式匹配,因为它没有任何数据构造函数公开。这是Haskell中的一种常见做法,因为它允许作者更新其数据类型的内部表示,而无需对其模块的用户进行重大更改 因此,使用阵列的唯一方法是使用模块提供的功能。要访问数组中的第一

Hi total Haskell初学者:数组函数中的模式是什么样的?例如:我只想向数组中的第一个元素添加+1

> a = array (1,10) ((1,1) : [(i,( i * 2)) | i <- [2..10]])

我希望您理解我的问题:)

您无法在阵列上进行模式匹配,因为它没有任何数据构造函数公开。这是Haskell中的一种常见做法,因为它允许作者更新其数据类型的内部表示,而无需对其模块的用户进行重大更改

因此,使用
阵列的唯一方法是使用模块提供的功能。要访问数组中的第一个值,可以使用
边界
(!)
的组合,或者从
关联中获取第一个键/值对。然后可以使用
(//)
对阵列进行更新

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
包缺少很多方便的函数。与操作在其他语言中的实现方式相比,上述所有解决方案都相当冗长

为了解决这个问题,我们有一个包(及其同类),它为Haskell添加了大量方便的函数,并使像
array
这样的包更容易接受。这个软件包有一个相当陡峭的学习曲线,但它的使用非常普遍,绝对值得学习

import Control.Lens

arraytest arr = arr & ix (fst (bounds arr)) +~ 1

如果你眯起眼睛,你几乎可以看到它是怎么说的,
arr[0]+=1
,但我们仍然没有牺牲任何不变性的好处。

这更像是对@4castle答案的扩展评论。不能在
数组上进行模式匹配,因为它的实现是隐藏的;您必须使用它的公共API来处理它们。但是,您可以使用公共API定义这样的模式(使用适当的语言扩展):

{-#语言模式同义词,视图模式#-}
--模式同义词:定义模式而不实际定义类型
--ViewPatterns:构造应用函数和匹配子模式的模式
进口管制。箭头(&&&&))——完全是为了躲避丑陋的羔羊;如果你愿意的话
阵列::ixi=>(i,i)->[(i,e)]->阵列ie
--类型签名提示这是数组函数,但是双向的
阵列边界'assocs'(边界'assocs'))
--在与数组边界“assocs”匹配时,将边界&&&assocs应用于
--传入数组,并将结果元组匹配到(bounds',assocs')
其中Array=Array
--在表达式中使用数组与仅使用数组相同
数组测试(数组bs((i,x):xs))=数组bs((i,x+1):xs)

我相当肯定,与
[]
之间的转换会使性能变得非常糟糕。

您无法对阵列进行模式匹配。在线查找Data.Array中记录的函数。
Array
包中的不可变数组实际上并不打算这样使用。最好使用一个高级创建函数或冻结
STArray
IOArray
来“一次性”创建不可变数组。一旦它被创建,你通常不想修改它;如果阵列很大,那么这样做的成本相当高。我不知道有哪种产品质量的Haskell库可以用于真正高性能的不可变数组结构,但近年来已经有了一些很有希望的实验。
import Control.Lens

arraytest arr = arr & ix (fst (bounds arr)) +~ 1
{-# 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)