type Array a = Int -> a
emptyArray :: Array a
emptyArray i =
error ("Access to non-initialized index " ++ show i)
putIndex :: Array a -> Int -> a -> Array a
putIndex ar i v = ar'
where ar' j | j==i = v
| otherwise = ar j
getIndex :: Array a -> Int -> a
getIndex a i = (a i)
我不理解emptyArray
和putIndex
功能。
问题是:
j==i
?
v
属于a
或?在这种情况下,它不会返回数组。getIndex (putIndex emptyArray 1 3) 2
会产生错误
getIndex (putIndex emptyArray 1 3) 1
返回3似乎很清楚。答案 0 :(得分:6)
我不会直接回答您的所有问题,而是会尝试解释Array a
类型背后的基本原理。
数组可以被认为是具有特定属性的数据结构,即给定索引它可以返回与该索引关联的值。这意味着我们可以通过描述与特定索引关联的值来表征数组,这听起来非常像将输入(索引)映射到输出(该索引处的值)的函数。因此,如果您不想知道长度或哪些索引有效,则可以认为数组与函数没有区别。这是一个相当有限的数组定义,但作为一个学习练习,重要的是要看看如何通过考虑最重要的操作来将数据结构转换为函数。
的类型是什么
ar'
查看类型签名:
putIndex :: Array a -> Int -> a -> Array a
putIndex ar i v = ar'
所以ar :: Array a
,i :: Int
,v
:: a , and
ar':: Array a`。
ar'
模式何时匹配?
我假设您的意思是何时使用ar'
的定义。 ar'
是Array a
,这意味着它是一个函数Int -> a
。这意味着只要在其上调用getIndex
就会使用它。
何时是
j == i
?v
的类型是a
?在这种情况下,它不会返回数组
仔细查看putIndex
的定义。 ar'
是putIndex
的返回值,而不是v
。 v
是ar'
时j == i
的返回值。从v
的类型签名可以看出,a
的类型为putIndex
。 putIndex
是一个增强现有功能ar
的功能,首先为i == j
添加检查。
中会发生什么
otherwise = ar j
如果j /= i
,则不会返回v
(新值与索引i
相关联),而是查找原始索引j
中的值ar
。这可能更明确地说明为
putIndex originalArray indexToSet newValue = newArray
where
newArray j
| j == indexToSet = newValue
| otherwise = getIndex originalArray j
为什么
getIndex (putIndex emptyArray 1 3) 2
会产生错误?
基本上,您可以将索引查找转换为一堆嵌套的if语句:
putIndex emptyArray i0 x0 ==> \i -> if i == i0
then x0
else emptyArray i
putIndex (
putIndex emptyArray i0 x0
) i1 x1 ==> \i -> if i == i1
then x1
else if i == i0
then x0
else emptyArray i
putIndex (
putIndex (
putIndex emptyArray i0 x0
) i1 x1
) i2 x2 ==> \i -> if i == i2
then x2
else if i == i1
then x1
else if i == i0
then x0
else emptyArray i
依此类推,为每个新if-then-else
添加一个putIndex
的新图层。对于您的具体示例
putIndex emptyArray 1 3 ==> \i -> if i == 1
then 3
else emptyArray i
然后
getIndex (putIndex emptyArray 1 3) 2
等同于表达式
if 2 == 1 then 3 else emptyArray 2
答案 1 :(得分:4)
ar' :: Int -> a
putIndex ar i v
模式,这将始终匹配)j == i
调用结果函数/数组,那么i
(来自调用i
的{{1}} - putIndex
是参数对于本地函数j
)ar'
(您看到只在索引ar
更改数组i = j
中的每个索引都会产生错误 - emptyArray
您在putIndex
更改了此信息,但之后您将其调用i = 1
,因此它将使用i= 2
的定义emptyArray
(上面的otherwise
案例),这是错误i = 1
与putIndex
至3 也许你这样理解:emptyArray
是一个始终errors
然后你可以使用putIndex
来获得一个新的数组/函数,它的第一个参数与这个参数的作用相同 - 仅在索引i
它现在将返回{{1} } - 对于所有其他indizes v
,它将返回i
( index i中的旧函数/数组)。
ar i
实际上只是在索引中为调用函数/数组
以下是getIndex
出错的原因:
getIndex (putIndex emptyArray 1 3) 2
但对getIndex (putIndex emptyArray 1 3) 2
= (putIndex emptyArray 1 3) 2
{ inside putIndex you get i = 1, v = 3 and j = 2 here }
= emptyIndex 2
= error ...
而言:
getIndex (putIndex emptyArray 1 3) 1