【问题标题】:Is it possible to write a function in haskell: (r -> [a]) -> [r -> a])?是否可以在haskell中编写一个函数:(r -> [a]) -> [r -> a])?
【发布时间】:2014-09-03 22:30:25
【问题描述】:

它的倒数似乎是可能的。 因为我想象列表是产品,-> 是指数, (a*a*a...)^r = (a^r)*(a^r)....

既然我们可以定义逆 [a->r] -> a -> [r] 不应该定义这个吗?

【问题讨论】:

  • const [] 怎么样? ;) 我的意思是:函数应该做什么?
  • 我试图完成的是,如果一个函数返回一个值列表,我们应该能够创建一个函数列表,每个函数都应该捕获列表的一个索引。我在考虑: f &&& (g &&& (h ... ))) == (f, (g, (h, ...)))
  • 列表的实际代数解释是List A ~ 1 / (1 - A),而不是1 / (1 - A^R) = (1 / (1 - A))^R
  • This older answer of mine 可能感兴趣。

标签: haskell types inverse


【解决方案1】:

[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 + ...));在这里,幂律不起作用。

【讨论】:

  • 如果列表是有限的怎么办?我们仍然可以定义逆对吗?
  • @user3585010:你仍然可以定义 something,但它不会是同构。
  • @user3585010:如果列表是有限的,你会怎么做?例如,假设有一个函数Int -&gt; [Bool] 返回[],但100 除外,它返回[True, False]。您希望生成的 [Int -&gt; Bool] 列表包含什么内容?
  • 对于给定大小的有限列表(例如由长度索引的Vec)或无限流是可能的。它们的共同点(List 没有)是它们都可以表示为索引集中的函数。 Vec n a ≅ Fin n -&gt; aStream a ≅ Nat -&gt; a。在这种情况下,问题减少到调用flip。原始问题无法保证同质性——r 的一个值可能会产生一个长度的列表,而r 的另一个值可能会产生一个不同长度的列表。
【解决方案2】:

如果您愿意修复函数列表的大小,那么它会起作用。

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 作为dn 的“某种”左逆...只要我们围绕一些长度信息进行改组:

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

如果我们神奇地知道(a)对于每个r,结果列表[a]的长度是相同的并且(b)我们知道,它可以是dn的“某种”右逆长度(下面称为magic

id2 :: (a -> [b]) -> a -> [b]
id2 f = dn . up magic

这个答案基本上等同于copumpkins 对leftroundabout 答案的评论,但不是使用类型来执行它,而是手动传递(固定)长度信息。如果您使用updn 玩一会儿,您就会明白为什么这种方法通常不适用于列表。

【讨论】:

    【解决方案3】:

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

    这是因为r -&gt; [a]这个类型大致代表如下:

    1. 接受r 类型的输入
    2. 输出一个自然数n(包括无穷大)
    3. 输出n 类型a 值的列表

    举个例子

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

    相比之下,[r -&gt; a] 类型大致代表如下:

    1. 输出一个自然数n(包括无穷大)
    2. 在列表的每个n 元素中:
      1. 接受r 类型的输入
      2. 输出a类型的值

    这里的关键事实是列表的长度必须在知道r 输入之前生成。一般来说,这是无法做到的,因为长度可以取决于r,如上面的replicateA 示例所示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-12
      • 2011-01-22
      • 1970-01-01
      相关资源
      最近更新 更多