Haskell 为什么可以';我不能使用迭代来重复应用映射吗?

Haskell 为什么可以';我不能使用迭代来重复应用映射吗?,haskell,higher-order-functions,lifting,Haskell,Higher Order Functions,Lifting,我意识到,当我有嵌套的数据结构时,我一直在手动编写代码来深入研究它们。像这样: --one level Prelude> map (*2) [1,2,3] [2,4,6] --nested two levels Prelude> let t2 = map $ map (*2) Prelude> t2 [[1,2,3],[4,5,6]] [[2,4,6],[8,10,12]] --nested three levels Prelude> let t3 = map $ m

我意识到,当我有嵌套的数据结构时,我一直在手动编写代码来深入研究它们。像这样:

--one level
Prelude> map (*2) [1,2,3]
[2,4,6]

--nested two levels
Prelude> let t2 = map $ map (*2)
Prelude> t2 [[1,2,3],[4,5,6]]
[[2,4,6],[8,10,12]]

--nested three levels
Prelude> let t3 = map $ map $ map (*2)
Prelude> t3 [[ [1,2,3],[4,5,6] ],[ [1,2,3],[4,5,6] ]]
[[[2,4,6],[8,10,12]],[[2,4,6],[8,10,12]]]
因此,我想到,我应该能够自动构造一个函数,以便使用高阶函数深入研究嵌套数据结构:

Prelude> let t f n = (iterate map f) !! n

<interactive>:35:22:
    Occurs check: cannot construct the infinite type: b0 = [b0]
    Expected type: (a0 -> b0) -> a0 -> b0
      Actual type: (a0 -> b0) -> [a0] -> [b0]
    In the first argument of `iterate', namely `map'
    In the first argument of `(!!)', namely `(iterate map f)'
Prelude>让t f n=(迭代映射f)!!N
:35:22:
发生检查:无法构造无限类型:b0=[b0]
预期类型:(a0->b0)->a0->b0
实际类型:(a0->b0)->[a0]->[b0]
在'iterate'的第一个参数中,即'map'
在“(!!)”的第一个参数中,即“(迭代映射f)”
我突然想到

  • 我知道它会在它期望的地方找到一个列表…其他的东西
  • 我不知道如何解决这个问题——我是否应该编写代码来执行重复的应用程序,即使我认为迭代就是为了这个目的
  • 这似乎类似于“提升”的概念——但我不知道如何运用这种直觉
  • 问题是这些“迭代”有不同的类型。对于每个迭代,您都会得到一个额外的嵌套级别,因此您希望

    t f 0 :: a -> b
    t f 1 :: [a] -> [b]
    t f 2 :: [[a]] -> [[b]]
    
    但是
    iterate::(a->a)->a->[a]
    要求所有迭代都具有相同的类型。事实上,直接实现上述功能需要某种形式的依赖类型,因为返回类型取决于
    n
    的值

    除非你有充分的理由不这样做,否则我建议保持简单,只需写出所需的
    map
    调用数。可以使用模板Haskell生成它们,但这可能会带来更多麻烦

    但是,如果您有复杂的嵌套数据结构,您可能需要研究哪些数据结构可以自动处理在嵌套结构中应用此类转换的样板文件

    下面是一个简单的例子:

    > import Data.Generics
    > let t x = everywhere (mkT (*2)) x
    > :t t
    t :: Data a => a -> a
    > t [2,4,6]
    [4,8,12]
    > t [[2,4,6],[8,10,12]]
    [[4,8,12],[16,20,24]]
    > t (Just [(1, 2, 3), (4, 5, 6)])
    Just [(2,4,6),(8,10,12)]
    

    考虑一下
    (迭代映射f)的类型!!n
    。对于
    n=0
    [a]->[a]
    对于
    n=1
    [[a]]->[[a]]
    对于
    n=2
    ,您希望此表达式的类型取决于
    n
    的值。但这在Haskell中是不可能做到的,因为它不是一种依赖类型的语言。

    谢谢!作为Haskell noob的亲戚,这可能是我第一次碰到一个错误,表明语言的局限性,而不仅仅是我理解的局限性!现在…学习一些Agda:)这并不是说这是不可能的-只是不建议新手尝试这些东西,因为它们不地道。如果您有充分的理由这样做,那么您应该明确询问是否可以使用诸如类型级别编号之类的高级功能。如果可以在Agda中表达,那么可能也可以在Haskell中表达,因为它有很多类型级别的机制,通常可以在依赖类型的语言中找到。