是否可以在haskell中编写函数:(r - > [a]) - > [r - >一个])?

时间:2014-09-03 22:30:25

标签: haskell types inverse

它的反转似乎是可能的。 由于我认为列表是产品而->是取幂, (a*a*a...)^r = (a^r)*(a^r)....

既然我们可以定义逆[a->r] -> a -> [r],那么可以定义它吗?

3 个答案:

答案 0 :(得分:8)

[a] ≅ a*a*...仅适用于无限列表。对于这些,您所请求的功能实际上非常简单,尽管天真的实现效率不高:

type InfiList = []

unwind :: (r -> InfiList a) -> InfiList(r -> a)
unwind f = [ \x -> f x !! n | n <- [0..] ]

实际上,[a] ≅ 1 + a * (1 + a * (1 + ...));这里的幂律不起作用。

答案 1 :(得分:4)

如果您愿意修复功能列表的大小,那么它就可以正常工作。

dn :: [r -> a] -> (r -> [a])
dn fns r = map ($ r)

up :: Int -> (r -> [a]) -> [r -> a]
up n f = tabulate n (\i r -> f' r !! i)
  where 
   f' = cycle . f
   tabulate n f = map f [0..n-1]

现在我们可以将up作为&#34;类型的&#34;如果我们在一些长度信息中移动,那么dn的左逆...:

id1 :: [r -> a] -> [r -> a]
id1 ls = up (length ls) (dn ls)

它可以是&#34;&#34;&#34;&#34;&#34;如果我们神奇地知道(a)每个dn结果列表r的长度是相同的,并且(b)我们知道该长度(称为{{1),则[a]的右逆下面)

magic

此答案基本上等同于id2 :: (a -> [b]) -> a -> [b] id2 f = dn . up magic copumpkin的答案的评论,但不是使用类型I来传递(固定)长度信息手动。如果您稍微使用leftroundaboutup,您就会明白为什么这种事情一般不适用于列表。

答案 2 :(得分:1)

直观地说,如果事先不知道列表的长度,这是不可能的。

这是因为类型r -> [a]大致代表以下内容:

  1. 输入r
  2. 类型的输入
  3. 输出自然数n(包括无限)
  4. 输出n
  5. 类型的a值列表

    举个例子,拿

    replicateA :: Int -> [Char]   -- r = Int , a = Char
    replicateA 0 = []
    replicateA n = 'A' : replicate (n-1)
    

    相比之下,类型[r -> a]大致代表以下内容:

    1. 输出自然数n(包括无限)
    2. 在列表的每个n元素中:
      1. 输入r
      2. 类型的输入
      3. 输出a
      4. 类型的值
    3. 这里的关键事实是,在知道r输入之前,必须在之前生成列表的长度。通常,这不能完成,因为长度可以取决于r,正如上面的replicateA示例所示。