Haskell乘法指数

时间:2018-08-28 06:29:30

标签: haskell

如果我想返回一个元素是 等于输入列表的相应元素乘以其在列表中的位置,我可以执行以下操作:

ML :: [Int] -> [Int]
ML [] = []
ML (x:xs) =  x * x-1 : ML xs 

但是我输入[6,3,5,1]时得到的相应列表给出了[35,8,24,0]的结果
有没有类似的方式我可以得到[0,3,10,3]

4 个答案:

答案 0 :(得分:9)

是的,zipWith函数可以提供帮助:

ML :: [Int] -> Int -> [Int]
ML [] _ = []
ML (x:xs) n = x * n : ML xs n+1

返回zipWith (*) [0..] [6, 3, 5, 1]

当前代码不起作用,因为它只是在当前元素上调用[0, 3, 10, 3],但是zipWith是一个函数,它用索引列表(x * x - 1等于zip [0..] [6, 3, 5, 1]),然后评估传递的函数,该函数在每个元素上使用2个参数。类似于:

[(0, 6), (1, 3), (2, 5), (3, 1)]

因此,函数定义为:

map (uncurry (*)) $ zip [0..] [6, 3, 5, 1]

答案 1 :(得分:8)

您编写的代码(假设函数名称实际上是有效的函数名称,例如import { Component, OnInit} from '@angular/core'; import * as io from 'socket.io-client'; @Component({ selector: 'app-chatbox', templateUrl: './chatbox.component.html', styleUrls: ['./chatbox.component.css'], }) export class ChatboxComponent implements OnInit { socket; messages: string[] = []; constructor() { this.socket = io.connect('http://localhost:8000'); } ngOnInit() { this.initializeChatServer(); } initializeChatServer() { this.messages.push( 'test 55');//This line works this.socket.on('newmessage', data => { console.log('message -> ' + data.nick + '>' + data.msg); this.messages.push(data.msg); //Cannot read property 'push' of undefined }); } } )被解析为:

ml

这是因为ml :: [Int] -> [Int] ml [] = [] ml (x:xs) = ((x * x)-1) : (ml xs) (*)具有更高的固定性(优先级),而(+)的固定性也高于(:),而功能应用程序ml xs的固定性最高。 br /> 也就是说,您正在将每个元素更改为其正方形,然后减去1。

现在您真正想要的是某种了解元素索引的方法。
这可以通过在递归中使用额外的参数来实现。

ml :: Int -> [Int] -> [Int]
ml _ [] = []
ml i (x:xs) = x*i : ml (i+1) xs

但是请注意,我们函数的签名已更改,我们现在接受一个额外的Int参数,并且希望用户像ml 0 someList一样调用,但是我们不想依赖用户传递有效数据,我们希望用户仅传递列表。因此,我们可以将此函数重命名为其他名称,例如ml_internal并使用ml作为正确的代码

ml :: [Int] -> [Int]
ml xs = ml_internal 0 xs

ml_internal :: Int -> [Int] -> [Int]
ml_internal _ [] = []
ml_internal i (x:xs) = x*i : ml_internal (i+1) xs

现在我们不想公开ml_internal,我们可以通过将这段代码放在模块中并仅导出ml来实现,但是没有理由这样做。我们也可能不希望ml_internal可用于同一模块中的其他功能。因此,我们可以将ml_internal放在where的{​​{1}}子句中:

ml

现在,我们也可以省略ml :: [Int] -> [Int] ml xs = ml_internal 0 xs where ml_internal :: Int -> [Int] -> [Int] ml_internal _ [] = [] ml_internal i (x:xs) = x*i : ml_internal (i+1) xs 的类型签名,因为可以推断出它,并且在某些情况下,如果不启用称为ml_internal的语言扩展,编译器就无法正确处理显式签名。
我们还可以将ScopedTypeVariables重命名为ml_internal,这是此类构造的广泛使用的名称,以获取go的以下代码:

ml

答案 2 :(得分:4)

您实际上根本不需要查看索引即可解决此问题!试试这个实现:

ml :: Num a => [a] -> [a]
ml [] = []
ml (_:xs) = 0 : zipWith (+) xs (ml xs)

我们不是将第n个元素直接乘以n,而是安排将第n个元素的n个副本一次加在一起。肯定比使用显式乘法的迭代方法要慢,但是我认为它避免了一次索引就很有意义。

在实际代码中,我只会使用另一个答案中提出的zipWith (*)实现。

答案 3 :(得分:1)

s.connect()

尝试使用此方法。将元素的索引作为另一个参数传递:)