2017-06-23 33 views
3

我正在嘗試學習haskell,並且存在一個我無法弄清楚的特定錯誤。有人可以解釋這個錯誤?無法匹配'Integer'類型

robot (_name,_attack,_hp) = \ cmd -> cmd (_name,_attack,_hp) 

hp (_,_,h) = h 
getHp aRobot = aRobot hp 

setHp aRobot newHp = aRobot (\ (n,a,_) -> robot (n,a,newHp)) 

damage aRobot amount = let actualHp = getHp aRobot 
         in 
         setHp aRobot (actualHp - amount) 


makeKiller = robot ("Killer",10,200) 
makeBetty = robot ("Betty",5,300) 

----- Example of computation in ghci 

b = makeBetty 
b1 = damage b 34 

<interactive>:52:14: error: 
    * Couldn't match type `Integer' 
        with `(([Char], Integer, t1) -> t0) -> t0' 
     Expected type: (([Char], Integer, 
         (([Char], Integer, t1) -> t0) -> t0) 
         -> (([Char], Integer, t1) -> t0) -> t0) 
        -> t1 
     Actual type: (([Char], Integer, Integer) -> t1) -> t1 
    * In the first argument of damage, namely `b' 
     In the expression: damage b 34 
     In an equation for `b1': b1 = damage b 34 
    * Relevant bindings include b1 :: t1 (bound at <interactive>:52:1) 

有什麼損壞功能是錯誤的,任何人都可以向我解釋錯誤嗎?

預先感謝您!

+2

添加類型簽名。令人驚訝的是,只需在'hp'中添加一個類型簽名,並且您會注意到'aRobot'在某些情況下具有的類型。 – Zeta

回答

1

此代碼需要Rank2Types擴展名。

機器人貝蒂有類型((字符串,整數,整數) - > t) - > t。 此類型應該是多態類型。

功能損壞取Robot(其類型爲(String,Integer,Integer) - > t) - > t)作爲參數。 這樣的功能有2級多態。

{-# LANGUAGE Rank2Types #-} 

type Robot = forall t . ((String, Integer, Integer) -> t) -> t 

robot :: (String, Integer, Integer) -> Robot 
robot (_name,_attack,_hp) = \ cmd -> cmd (_name,_attack,_hp) 

hp :: (String, Integer, Integer) -> Integer 
hp (_,_,h) = h 

getHp :: Robot -> Integer 
getHp aRobot = aRobot hp 

setHp :: Robot -> Integer -> Robot 
setHp aRobot newHp = aRobot (\ (n,a,_) -> robot (n,a,newHp)) 

damage :: Robot -> Integer -> Robot 
damage aRobot amount = let actualHp = getHp aRobot 
         in 
         setHp aRobot (actualHp - amount) 


makeKiller :: Robot 
makeKiller = robot ("Killer",10,200) 

makeBetty :: Robot 
makeBetty = robot ("Betty",5,300) 

如果沒有等級2的類型,getHp和setHp要求的機器人類型是不匹配的。函數getHp要求((String,Integer,Integer) - > Integer) - > Integer作爲機器人類型。函數setHp需要((String,Integer,Integer) - > Robot) - > Robot。

簡化版本在這裏。

fun :: (a -> a) -> Char -> Int -> (Char, Int) 
fun f c n = (f c, f n) 

此定義會導致類型錯誤。

{-# LANGUAGE Rank2Types #-} 

fun :: (forall a . a -> a) -> Char -> Int -> (Char, Int) 
fun f c n = (f c, f n) 

這個定義還可以!

+1

謝謝! 不幸的是,目前我還沒有意識到許多語言特徵,這就是爲什麼我無法弄清楚這個問題。 VS代碼提示我那種類型的簽名,但我不明白爲什麼。 我會用你的答案作爲未來的參考:) –

+1

這可能是@StefanoCerruti所要求的,但我懷疑這是他的需要。機器人不需要是一個功能。 – overactor

+0

謝謝。也許他需要ADT。 – YoshikuniJujo

1

你可能不需要機器人是一個函數,只是聲明爲一個類型,這是一個元組:

type Robot = (String, Integer, Integer) 

getHp :: Robot -> Integer 
getHp (_, _, hp) = hp 

setHp :: Robot -> Integer -> Robot 
setHp (name, attack, _) hp = (name, attack, hp) 

damage :: Robot -> Integer -> Robot 
damage r dmg = setHp r $ getHp r - dmg 

makeKiller :: Robot 
makeKiller = ("Killer", 10, 200) 

makeBetty :: Robot 
makeBetty = ("Betty", 5, 300) 

b = makeBetty 
b1 = damage b 34 

或者,你可以把機器人的algebraic data type,這肯定將不僅僅是使用更好的一個元組。

相關問題