有这段代码,它试图描述一个机器人对象:
robot (name, attack, hp) = \message -> message(name, attack, hp)
name (n, _, _) = n
attack (_, a, _) = a
hp (_, _, hp) = hp
getAttack aRobot = aRobot attack
getHP aRobot = aRobot hp
getName aRobot = aRobot name
setName aRobot newName = aRobot(\(n, a, h) -> robot(newName, a , h))
setAttack aRobot newAttack = aRobot(\(n, a, h) -> robot(n, newAttack , h))
setHP aRobot newHP = aRobot(\(n, a, h) -> robot(n, n , newHP))
printRobot aRobot = aRobot( \(n, a, h) -> n ++ " attack: " ++ (show a) ++ " hp: " ++ (show h) )
damage aRobot dmg = aRobot(\(n,a,h) -> robot(n,a, h - dmg))
fight aRobot defender = damage defender dmg
where dmg = if getHP aRobot > 0
then getAttack aRobot
else 0
getAllHP aRobots = map getHP aRobots
现在我需要编写一个函数,在一轮后返回两个机器人的元组,我这样做:
oneRoundFight aR1 aR2 = ( fight aR1 aR2, fight aR2 aR1 )
一个错误:
*Main> :l robot.hs
[1 of 1] Compiling Main ( robot.hs, interpreted )
robot.hs:27:48: error:
* Occurs check: cannot construct the infinite type:
b2 ~ ((a2, b2, b1) -> t1) -> t1
Expected type: ((a2, ((a2, b2, b1) -> t1) -> t1,
((a2, b2, b1) -> t1) -> t1)
-> ((a2, b2, b1) -> t1) -> t1)
-> a1
Actual type: ((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1
* In the first argument of `fight', namely `aR2'
In the expression: fight aR2 aR1
In the expression: (fight aR1 aR2, fight aR2 aR1)
* Relevant bindings include
aR2 :: ((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1
(bound at robot.hs:27:19)
aR1 :: ((a, ((a, b, a1) -> t) -> t, ((a, b, a1) -> t) -> t)
-> ((a, b, a1) -> t) -> t)
-> b1
(bound at robot.hs:27:15)
oneRoundFight :: (((a, ((a, b, a1) -> t) -> t,
((a, b, a1) -> t) -> t)
-> ((a, b, a1) -> t) -> t)
-> b1)
-> (((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1)
-> (a1, b1)
(bound at robot.hs:27:1)
|
27 | oneRoundFight aR1 aR2 = ( fight aR1 aR2, fight aR2 aR1 )
| ^^^
robot.hs:27:52: error:
* Occurs check: cannot construct the infinite type:
b ~ ((a, b, a1) -> t) -> t
Expected type: ((a, b, a1) -> ((a, b, a1) -> t) -> t) -> b1
Actual type: ((a, ((a, b, a1) -> t) -> t, ((a, b, a1) -> t) -> t)
-> ((a, b, a1) -> t) -> t)
-> b1
* In the second argument of `fight', namely `aR1'
In the expression: fight aR2 aR1
In the expression: (fight aR1 aR2, fight aR2 aR1)
* Relevant bindings include
aR2 :: ((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1
(bound at robot.hs:27:19)
aR1 :: ((a, ((a, b, a1) -> t) -> t, ((a, b, a1) -> t) -> t)
-> ((a, b, a1) -> t) -> t)
-> b1
(bound at robot.hs:27:15)
oneRoundFight :: (((a, ((a, b, a1) -> t) -> t,
((a, b, a1) -> t) -> t)
-> ((a, b, a1) -> t) -> t)
-> b1)
-> (((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1)
-> (a1, b1)
(bound at robot.hs:27:1)
|
27 | oneRoundFight aR1 aR2 = ( fight aR1 aR2, fight aR2 aR1 )
| ^^^
Failed, no modules loaded.
Prelude>
我不太明白这个输出是什么意思,特别是cannot construct the infinite type:
,如果你改变地方的参数:( fight aR1 aR2, fight aR1 aR2 )
那么这个错误就不会发生。
你能解释一下吗?
同时,函数fight
编写并工作:
Prelude> :l robot.hs
[1 of 1] Compiling Main ( robot.hs, interpreted )
Ok, one module loaded.
*Main> aR1 = robot("r1", 8, 100)
*Main> aR2 = robot("r2", 4, 120)
*Main> aR2_damaged = fight aR1 aR2
*Main> aR1_damaged = fight aR2 aR1
*Main> printRobot aR1_damaged
"r1 attack: 8 hp: 96"
*Main> printRobot aR2_damaged
"r2 attack: 4 hp: 112"
你确定吗。那为了存储这么简单的数据集,你真的需要这么复杂的数据类型(从函数到元组的函数)吗?
如果是这样,那么您将不得不处理更高级别的多态性,而这几乎不是您现在想要处理的。
如果没有,那么一切都可以更容易地描述。
“没有额外的实体”