次のコードはタイプチェックに失敗します:
surfDim :: SDL.V2 CInt
surfDim = SDL.surfaceDimensions surfIn
完全なエラー:
* Couldn't match type `SDL.V2 CInt' with `CInt'
Expected type: SDL.V2 CInt
Actual type: SDL.V2 (SDL.V2 CInt)
* In the expression: SDL.surfaceDimensions surfIn
In an equation for `surfDim':
surfDim = SDL.surfaceDimensions surfIn
In an equation for `scaleSurface':
scaleSurface surfIn box scale
= do surfOut <- createScreenSurface sizeCIntScaled
_ <- SDL.surfaceBlitScaled
surfIn
(Just (fmap fromIntegral boxFinal))
surfOut
(Just boxFinalScaled)
return surfOut
where
boxFinal
= case box of
Just b -> b
Nothing
-> SDL.Rectangle
origin (fmap (fmap fromIntegral) (SDL.surfaceDimensions surfIn))
boxFinalScaled
= fmap (fromIntegral . (* (fromIntegral scale))) boxFinal
sizeCIntScaled = boxSize boxFinalScaled
origin :: SDL.Point SDL.V2 Int
....
|
232 | surfDim = SDL.surfaceDimensions surfIn
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
次のコードを見た後、私はまだ混乱していますsurfaceDimensions
:
surfaceDimensions :: MonadIO m => Surface -> m (V2 CInt)
surfaceDimensions (Surface s _) = liftIO $ (V2 <$> Raw.surfaceW <*> Raw.surfaceH) <$> peek s
のでV2
(当然私には)MonadIOのインスタンスを持っていないようだ、なぜこれが起こっている私は知らないが、私の最高の推測では、それはそれを満たしていることを、なぜ、またはどのように(おそらくのために、私は知りません私のliftIOの不完全な理解)。
そうではありません。エラーメッセージを報告する前に、タイプチェッカーが可能な限り統合する傾向に反しています。この場合、型チェッカーは、「ああ、この式には型m something
があり、私はV2 something
。が欲しい。だから、そうでm
なければならないV2
」と考えます。それは、後でm = V2
そのMonadIO
制約を満たすかどうかをチェックするまで延期します。それはそこに着く前に、それはトップレベルの型の内側に見え、それが統一できないことを実現V2 CInt
してCInt
、それがするかどうかをチェックし、これまでに失敗したので、V2
モナドです。
人間として、あなたは自分の仮定のどれが間違っていたかをバックアップして質問することによって間違っていることに反応するかもしれません。タイプチェッカーはそれをまったく行いません。代わりに、先に進むことが不可能になるまで、すべての仮定は問題がなかったと仮定します。それからそれは最後のステップについて不平を言います。それまでに奇妙なウサギの穴を掘り下げることはかなり一般的です。そのため、Haskellの型エラーは、特にここにあるような型クラスが関係している場合は、悪名高いほど悪いものです。
さて、これが実際の間違いです。IO
モナド(またはのその他のインスタンスMonadIO
)の次元を計算する必要があります。つまり、次のことを行う必要があります。
surfDim <- SDL.surfaceDimensions surfIn
いくつかの適切なdo
ブロックで。常微分方程式にすることはできません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加