Haskell中的多项式

时间:2011-08-29 16:21:10

标签: haskell functional-programming

我星期四有关于函数式编程的考试,我很确定我将不得不用多项式做一个TAD。我正在这样添加多项式:

type Pol = [(Int,Int)] 

suma :: Pol -> Pol -> Pol
suma [] ys = ys
suma xs [] = xs
suma ((c1,g1):xs) ((c2,g2):ys)
    | g1 == g2  = ((c1+c2,g1):(suma xs ys))
    | g1 > g2 = ((c1,g1):(suma xs ((c2,g2):ys)))
    | g1 < g2 = ((c2,g2):(suma ((c1,g1):xs) ys))

它完美有效,但老师不喜欢。她更喜欢这样做:

data Pol = P [(Int,Int)] deriving Show

一开始,我虽然很容易改变结构,但并不是因为我在编译中遇到了很多麻烦。有人可以帮我吗?我试过这种方式,但它不起作用:

data Pol = P [(Int,Int)] deriving Show

suma :: Pol -> Pol -> Pol
suma (P []) (P ys) = P ys
suma (P xs) (P []) = P xs
suma (P ((c1,g1):xs)) (P ((c2,g2):ys))
    | g1 == g2  = P ((c1+c2,g1):suma (P xs) (P ys))
    | g1 > g2   = P ((c1,g1):(suma (P xs) (P ((c2,g2):ys))))
    | g1 < g2   = P ((c2,g2):(suma (P ((c1,g1):xs)) (P ys)))

我收到此错误:

ERROR file:.\Febrero 2011.hs:7 - Type error in application
*** Expression     : P (c1 + c2,g1) : suma (P xs) (P ys)
*** Term           : suma (P xs) (P ys)
*** Type           : Pol
*** Does not match : [a]

非常感谢你!

3 个答案:

答案 0 :(得分:3)

如果某些内容不起作用,请在问题中解释原因。如果有编译错误,请发布。

在这种情况下,问题是suma的最后一个分支中的类型错误。看看

suma (P ((c1,g1):xs)) (P ((c2,g2):ys))
    | g1 == g2  = P ((c1+c2,g1):suma (P xs) (P ys))

P ((c1+c2,g1):suma (P xs) (P ys))中,您尝试使用

创建类型[(Int,Int)]的列表
(c1+c2,g1):suma (P xs) (P ys)

您正在尝试构建一个类型为(Int,Int)的头部列表,但是类型为Pol的尾部(结果类型为suma)。其他案件也有类似的错误。

答案 1 :(得分:2)

让suma在List上工作:

suma :: [(Int,Int)] -> [(Int,Int)] -> [(Int,Int)]
suma [] ys = ys
suma xs [] = xs
suma ((c1,g1):xs) ((c2,g2):ys)
    | g1 == g2  = ((c1+c2,g1):(suma xs ys))
    | g1 > g2 = ((c1,g1):(suma xs ((c2,g2):ys)))
    | g1 < g2 = ((c2,g2):(suma ((c1,g1):xs) ys))

然后Pol的Sum可以定义为:

sumPol :: Pol -> Pol -> Pol
sumPol (P a) (P b) = P (suma a b)

如果你想要更时尚或monadic :)那么你可以让Pol成为monad并使用do notation来做这些事情

答案 2 :(得分:0)

首先,让我们考虑您的原始代码

type Pol = [(Int,Int)] 

suma :: Pol -> Pol -> Pol
suma [] ys = ys
suma xs [] = xs
suma ((c1,g1):xs) ((c2,g2):ys)
    | g1 == g2  = ((c1+c2,g1):(suma xs ys))
    | g1 > g2 = ((c1,g1):(suma xs ((c2,g2):ys)))
    | g1 < g2 = ((c2,g2):(suma ((c1,g1):xs) ys))

如果你这样做:

let p1 = [(5,0),(1,1),(7,2)]::Pol
let p2 = [(1,2),(3,1),(2,0)]::Pol

然后你得到:

suma p1 p2
[(1,2),(3,1),(7,0),(1,1),(7,2)]

这不是“错误的”,但这并不是人们对两个多项式求和所期望的结果:你可能希望得到简化形式的结果:

[(7,0),(4,1),(8,2)]

还有一条评论:你了解了Haskell record syntax吗?我认为它可以简化您的工作并使事情得到澄清。这是一个提示:

data Term = Term { coeff :: Int,
                   expnt :: Int
                 } deriving Show

data Pol = Pol { terms :: [Term] } deriving Show

有了这个,在不简化结果的情况下求和两个多项式就像...连接它们的术语一样简单:) ......并且一切都可以显示:

Main> let p1 = Pol [Term 5 0, Term 1 1, Term 7 2]
Main> p1
Pol {terms = [Term {coeff = 5, expnt = 0},Term {coeff = 1, expnt = 1},Term {coeff = 7, expnt = 2}]}
Main> let p2 = Pol [Term 1 2, Term 3 1, Term 2 0]
Main> p2
Pol {terms = [Term {coeff = 1, expnt = 2},Term {coeff = 3, expnt = 1},Term {coeff = 2, expnt = 0}]}
Main> let p3 = sumpol p1 p2
Main> p3
Pol {terms = [Term {coeff = 5, expnt = 0},Term {coeff = 1, expnt = 1},Term {coeff = 7, expnt = 2},Term {coeff = 1, expnt = 2},Term {coeff = 3, expnt = 1},Term {coeff = 2, expnt = 0}]}

简化多项式有点棘手,但这是一个很好的练习。

我希望这会有所帮助。