在Haskell中将函数从实数提升到复数

时间:2018-01-26 16:20:18

标签: haskell applicative

我编写了一个函数,它接受一个列表和一个数字,并返回一个移位反转的总和:

sumInvZ::[Float]->Float->Float
sumInvZ zList z = let invList = [if z==x then 0 else 1/(z-x)|x<-zList] in foldr (+) 0 invList

我想概括这个函数来处理复数。一个简单的解决方案就是重写它:

import Data.Complex

sumInvZC::[Complex Float]->Complex Float->Complex Float
sumInvZC zList z = let invList = [if z==x then 0 else 1/(z-x)|x<-zList] in foldr (+) 0 invList

但是我也有兴趣使用Complex monad来直接提升我的SumInvZ。我已经玩过各种各样的liftM,但我还是找不到办法让它发挥作用。有可能吗?

1 个答案:

答案 0 :(得分:6)

你不能使用Complex Monad或Functor,因为那些只是按分数运算复数(注意分量乘法和复数乘法完全不同)。

考虑使用Fractional类型类:

sumInvZ :: (Fractional f, Eq f) => [f] -> f -> f
sumInvZ zList z = let invList = [if z==x then 0 else 1/(z-x)|x<-zList] in
    foldr (+) 0 invList

顺便说一句,你可以用更易读的方式重写函数:

sumInvZ :: (Fractional f, Eq f) => [f] -> f -> f
sumInvZ zList z = sum [if z==x then 0 else 1/(z-x) | x <- zList]

另请考虑@leftaroundabout建议的两种变体:

sumInvZ zList z = sum [1/(z-x) | x<-zList, x/=z]

或者,交换参数,

sumInvZ z = sum . map (recip . (z-)) . filter (/=z)