好的,为了继续my previous questions,我有一个名为Enumeration
的类型,它被描述为
现在,枚举是有限桶的无限序列, 用自然数索引
定义如下:
> type Nat = Int
> type Enumeration a = Nat -> Finite a
这是Finite Bucket
> type Finite a = [a]
因此,如果我理解正确,Enumeration
就像列表一样?它是一个从Int到列表的函数,它应该像索引一样使用int,并返回一个列表。
但我无法理解的是,它是否确实是一个列表列表,它在哪里存储它"列表"所以它可以稍后使用我提供的index
返回它们。
我已经在此Enumeration
类型上定义了一些功能,但我不确定它们是否正确,因为我不确定我是否真的理解了Enumeration
是
例如:
定义一个函数来进行单例枚举。 为简单起见,我建议您将唯一的项目放入存储桶0中。
> singleE' :: a -> Enumeration a
> singleE' a 0 = singleF a
定义枚举映射:
> imapE :: (a -> b) -> Enumeration a -> Enumeration b
> imapE f g = (imapF f) . g
定义枚举的不相交联合:
为简单起见,您可以逐桶执行此操作:结果枚举的存储桶i中的项目应该从存储桶i中获取 两个参数枚举。
> plusE :: Enumeration a -> Enumeration b -> Enumeration (Either a b)
> plusE f g = \n -> [Left x | x <- f n] ++ [Right y | y <- g n]
定义枚举的笛卡尔积
这比较棘手,因为你不能再一桶一桶了, 正如你为plusE所做的那样(为什么不呢?)。最简单的技术就是执行 一种卷积:结果枚举的桶i中的项目 应该从第一个论点的第j栏中的那些构造出来 并且在第二个桶k中,其中j + k = i。
> timesE :: Enumeration a -> Enumeration b -> Enumeration (a,b)
> timesE f g = \n -> timesF (f n) (g n)
所以我的问题是:
我是否正确理解了Enumeration
的类型
如果我这样做,我定义的函数是否正确?
答案 0 :(得分:2)
我们可以证明Enumeration a
(大多数)与列表列表同构。
&#34;同构&#34;由以下函数给出:
enumerationToLists :: Enumeration a -> [[a]]
enumerationToLists f = map f [0..]
listsToEnumeration :: [[a]] -> Enumeration a
listsToEnumeration xss i = head $ drop i (xss++empties)
其中:
empties :: [[a]]
empties = []:empties
由于引用透明度,我们可以使用&#34;等式推理&#34;就像在数学中所做的那样,证明它们确实形成了一种同构性,并且#34;
证明listsToEnumeration . enumerationToLists = id
:
(listsToEnumeration . enumerationToLists) f
by definition of .
= listsToEnumeration (enumerationToLists f)
by definition of enumerationToLists
= listsToEnumeration (map f [0..])
by definition of map
= listsToEnumeration [f 0, f 1, f 2, ...]
by definition of listsToEnumeration
= \i -> head $ drop i ([f 0, f 1, f 2, ...]++empties)
concatenation of infinite lists
= \i -> head $ drop i [f 0, f 1, f 2, ...]
by definition of drop and of the argument
= \i -> head $ [f i, f (i+1), f (i+2), ...]
by definition of head
= \i -> f i
eta reduction (i.e. \x -> f x = f)
= f
现在,鉴于xss = [xs1, xs2, ..., xsN]
和empties = []:empties
,我们有(enumerationToLists . listsToEnumeration) (xss++empties) = xss++empties
(enumerationToLists . listsToEnumeration) (xss++empties)
by definition of .
= enumerationToLists (listsToEnumeration (xss++empties))
by definition of listsToEnumeration
= enumerationToLists (\i -> head $ drop i (xss++empties++empties))
concatenation of infinite lists
= enumerationToLists (\i -> head $ drop i (xss++empties))
by definition of empties
= enumerationToLists (\i -> head $ drop i [xs1, xs2, ..., xsN, [], [], ...])
by definition of enumerationToLists
= map (\i -> head $ drop i [xs1, xs2, ..., xsN, [], [], ...]) [0..]
by definition of map
= let f = (\i -> head $ drop i [xs1, xs2, ..., xsN, [], [], ...]) in [f 0, f 1, ...]
by definition of f
= [head $ drop 0 [xs1, xs2, ..., xsN, [], ...], head $ drop 1 [xs1, xs2, ..., xsN, [], ...], ...]
by definition of drop
= [head [xs1, xs2, xsN, [], ...], head [xs2, ... xsN, [], ..], ..., head [xsN, [],...], head [[], ...], ..]
by definition of head
= [xs1, xs2, ..., xsN, [], [], ...]
by definition of xss, empties and ++
= xss ++ empties
显然,我们假设Enumeration a
是总数(它应该返回[]
用于&#34;未定义的索引&#34;)。如果我们限制列表的无限列表,则上面的两个函数是同构,否则它只保持&#34;直到++empties
&#34; (如果xss
是无限的,我们有xss = xss++empties
,因为我们永远无法访问空帐部分。)
所以,如果你想保持这种同构性&#34;你应该确保所有的功能都是完整的(看singleE'
...),但除此之外他们看起来很好。
我希望上面的例子能说明如何判断你定义的函数是否正确。