私は現在、ライブラリを使って簡単な関数を書くことによってレンズライブラリを学習しています。残念なことに、私はコンパイラのエラーが生成されて混乱しているので、以下の関数dmg
の最初の2つの関数は正しくコンパイルされますが、最後は失敗するのはなぜですか?Control.Lensを使用して関数を正しくフォーマットするにはどうすればよいですか?
import Control.Lens
type Health = Int
type Damage = Int
data Card = Card {
_health :: Int,
_damage :: Int
} deriving (Show,Eq)
health :: Lens' Card Health
health = lens _health (\card h -> card { _health = h })
damage :: Lens' Card Damage
damage = lens _damage (\card d -> card { _damage = d })
cardDead :: Card -> Bool
cardDead c = c^.health <= 0
duel :: (Card,Card) -> (Card,Card)
duel (c,c2) = ((dmg c c2),(dmg c2 c))
本物の肉です。
dmg :: Card -> Card -> Card
dmg myCard otherCard = over health ((-) (otherCard^.damage)) myCard --compiles
dmg myCard otherCard = myCard & health %~ ((-) (otherCard^.damage)) --compiles
dmg myCard otherCard = health %~ ((-) (otherCard^.damage)) myCard --compile error
私の質問は3つの部分に分かれています。
なぜ3番目のdmg関数がコンパイルに失敗しますか?
(%~)
演算子をまだ使用するにはどうすればいいですか?(&)
は使用せず、まだコンパイルしますか?dmg
を書くのに最も美しく、慣用的なレンズの方法は何ですか?
- 参考
は、ここにあなたがレンズなしのdmgを書くでしょう可能性が一つの方法である
dmg myCard otherCard =
let
damageTaken = _damage otherCard
oldHealth = _health myCard
newHealth = oldHealth - damageTaken
in myCard {_health = newHealth}
編集:参考のために、ここで私はトラブルに理解を持っていたエラーメッセージがあります(間違って書かれた)ライン3.
*Main GHC.Arr Control.Applicative Control.Lens> :l Doom.hs
[1 of 1] Compiling Main (Doom.hs, interpreted)
Doom.hs:26:24:
Couldn't match expected type `Card' with actual type `Card -> Card'
In the expression: health %~ ((-) (otherCard ^. damage)) myCard
In an equation for `dmg':
dmg myCard otherCard = health %~ ((-) (otherCard ^. damage)) myCard
Doom.hs:26:51:
Couldn't match type `Health -> Health' with `Int'
Expected type: Getting (Health -> Health) Card (Health -> Health)
Actual type: (Damage -> Const (Health -> Health) Damage)
-> Card -> Const (Health -> Health) Card
In the second argument of `(^.)', namely `damage'
In the first argument of `(-)', namely `(otherCard ^. damage)'
Doom.hs:26:60:
Couldn't match expected type `Health -> Health'
with actual type `Card'
In the second argument of `(-)', namely `myCard'
In the second argument of `(%~)', namely
`((-) (otherCard ^. damage)) myCard'
Failed, modules loaded: none.
Prelude GHC.Arr Control.Applicative Control.Lens>
"混乱しているコンパイルエラー"については、実際にそれらを含めるべきです。 – Carl
良い点。以下の答えはかなり完璧でしたが、後世のために私がP3をコンパイルしている間違いが含まれています。 – SolventGren