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中表达,因为它有很多类型级别的机制,通常可以在依赖类型的语言中找到。