繁体   English   中英

在Haskell中计算`[1,x ^ 1,x ^ 2,…,x ^ n]`

[英]calculate `[1, x^1, x^2, …, x^n]` in Haskell

我如何像下面这样在Haskell中编写powerList函数? 我想用n乘法运算来构建这样一个列表,其中每个元素都是前一个元素的简单倍数,而不是n指数运算。

理想情况下,实现是干净,惯用的Haskell,并且相当有效。

-- powerList x n -> [1, x, x^2, ..., x^n]
-- For example:
-- powerList 2 0 -> [1]
-- powerList 2 1 -> [1, 2]
-- powerList 2 2 -> [1, 2, 4]
-- powerList 2 3 -> [1, 2, 4, 8]
-- powerList 2 4 -> [1, 2, 4, 8, 16]
powerList :: forall a. Integral a => a -> a -> [a]
powerList _ 0 = [1]
powerList x n = [] -- ??? 

对于每个元素都是前一个元素的函数的列表,可以使用iterate

 iterate :: (a -> a) -> a -> [a] 

iterate fx返回fx的重复应用的无限列表:

 iterate fx == [x, fx, f (fx), ...] 

Prelude> powerList x n = take (n + 1) $ iterate (* x) 1
Prelude> powerList 2 0
[1]
Prelude> powerList 2 4
[1,2,4,8,16]

如果你想不使用iteratetake的做法,我想通过看如何开始iterate实现:

iterate f i = i : iterate f (f i)

为了执行类似的操作,我们的递归函数将需要一个附加参数i 在编写递归函数时,这是一种非常常见的技术。

-- powerList x n = [ 1, x, x^2, ..., x^n ]
powerList x n = powerList' n 1
  where
    -- powerList' n i = [ i, i*x, i*x^2, ..., i*x^n ]
    powerList' 0 i = [ i ]
    powerList' n i = i : powerList' (n - 1) (i * x)

列表理解通常是生成器的简写。 生成器在其他功能中有多种用途。 列表理解通常足够简洁,可以在函数中内联。 以下是powerList函数的列表理解版本。 它简称为p。 我很懒。 结果中的两个值是每个值的笛卡尔积。 也是第一个参数的常数仅需要一次。 去搞清楚。

Prelude> p i j = [(k ^ n) | k <- [i], n <- [0..j]]
Prelude> p 2 16
[1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536]

大笑的事实是,i或k是常量和参数,可以使用。

p i j = [(i ^ n) | n <- [0..j] ]

我发现Haskell最引人注目的是,上面的函数是规范而不是指令。 Haskell的许多功能告诉计算机需要什么,而不是做什么来获得它,也就是说,它具有很大的说明性,这是语言中最想要的。

编辑4/5/2018,我很抱歉。 我的最后一个函数未满足您将最后一个值乘以一个因子的规范。 您的规范实际上是递归的。 “其中每个元素都是前一个元素的简单倍数,而不是n个指数运算。” 下面的函数正是这样做的。

pow l = l ++ pow [(last l) * 2]

但是就像迭代一样,它是无限的。 使用take x $ pow [1]使其不会永远运行。

克里斯的答案很可能就是您想要的。

如果您想在不使用迭代的情况下进行操作,则可以使用以下代码。

编辑:为避免附加到列表的尾部(花费线性时间),可以使用辅助函数powerList'首先反向计算列表,然后反转该函数的输出以更正顺序。

powerList' :: Integral a => a -> a -> [a]
powerList' _ 0 = [1]
powerList' x n = do { let l = go x (n - 1)
                    ; [x * (head l)] ++ l
                    }
powerList :: Integral a => a -> a -> [a]
powerList x n = reverse (powerList' x n)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM