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

时间:2016-09-17 03:51:01

标签: haskell

如何在Haskell中编写n函数,如下所示?我希望用n乘法运算构建这样一个列表,其中每个元素都是前一个元素的简单倍数,而不是-- 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 = [] -- ??? 指数运算。

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

FindFirst()

3 个答案:

答案 0 :(得分:12)

对于每个元素都是前一个元素的函数的列表,您可以使用https://github.com/ccnokes/electron-tutorials/tree/master/preload-scripts

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

iterate f x会返回fx重复申请的无限列表:

iterate f x == [x, f x, f (f x), ...]
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)

答案 1 :(得分:2)

列表推导通常是生成器的简写。生成器在其他功能中用于许多目的。列表推导通常足够简洁,可以在函数中包含内联。以下是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]

LOL一个明显的事实,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]不要让它永远运行。

答案 2 :(得分:1)

克里斯的回答很有可能是你要找的。

如果您不想使用iterate,可以使用以下代码。

编辑:为了避免附加到列表尾部(需要线性时间),可以使用辅助函数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)