为什么surfaceDimensions(出现)到return一个双重封闭的向量(V2 V2 CInt)?
Why does surfaceDimensions (appear) to return a doubly enclosed vector (V2 V2 CInt)?
以下代码无法进行类型检查:
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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我看了 the code for surfaceDimensions
后还是一头雾水:
surfaceDimensions :: MonadIO m => Surface -> m (V2 CInt)
surfaceDimensions (Surface s _) = liftIO $ (V2 <$> Raw.surfaceW <*> Raw.surfaceH) <$> peek s
自从 V2
(对我来说是正确的)doesn't seem to have an instance of MonadIO, I don't know why this is happening, but my best guess is that it is satisfying it and I don't know why or how (probably due to my incomplete understanding of liftIO)。
这里有两个问题 - 让您的代码编译,并从 GHC 获得更好的错误消息。如果您 post 更多代码,我们可以在第一个方面提供更多帮助。
如果您不使用 surfDim
的类型签名,您会得到更有用的错误吗?
V2 CInt
和 V2 (V2 CInt)
都不是可能的类型。你需要像 IO (V2 CInt)
这样的东西来满足 MonadIO m
。
GHC 尝试为 m
选择一个类型,在 V2 CInt
类型 sig 的指导下,并决定 m ~ V2
。不幸的是,这个选择并没有产生有用的错误信息。如果您使用建议的类型 sig 作为 "Actual type",我相信 GHC 将深入到类型检查过程中,以注意到没有实例 MonadIO V2
,正如您指出的那样。
我不知道是否有可能让 GHC 始终如一地就此类事情提供更好的建议。当我被类型错误难倒时,我喜欢尝试添加更多类型信号或删除一些。通常有不同的错误消息,对我来说,一个可能比另一个更有意义。
没有。您 运行 与类型检查器在报告错误消息之前尽可能统一的趋势相冲突。在这种情况下,类型检查器认为,"Oh, this expression has type m something
, and I want a V2 something
. So m
must be V2
." 它推迟到稍后检查 m = V2
是否满足 MonadIO
约束。在它到达那里之前,它查看了顶级类型,并意识到它不能统一 V2 CInt
和 CInt
,所以它在检查 V2
是否是一个 monad 之前就失败了.
作为一个人,您可能会通过支持和质疑您的哪些假设是错误的来回应错误。类型检查器根本不这样做。相反,它假设它的所有假设都很好,直到无法继续进行为止。然后它抱怨最后一步。到那时它已经掉进了一些奇怪的兔子洞是相当普遍的,这就是为什么 Haskell 类型错误是出了名的糟糕,尤其是当涉及类型 类 时。
现在,这是真正的错误。您需要计算 IO
monad(或 MonadIO
的其他实例)中的维度。这意味着你需要做:
surfDim <- SDL.surfaceDimensions surfIn
在一些适当的 do
块中。你不能把它变成一个普通的方程式。
以下代码无法进行类型检查:
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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我看了 the code for surfaceDimensions
后还是一头雾水:
surfaceDimensions :: MonadIO m => Surface -> m (V2 CInt)
surfaceDimensions (Surface s _) = liftIO $ (V2 <$> Raw.surfaceW <*> Raw.surfaceH) <$> peek s
自从 V2
(对我来说是正确的)doesn't seem to have an instance of MonadIO, I don't know why this is happening, but my best guess is that it is satisfying it and I don't know why or how (probably due to my incomplete understanding of liftIO)。
这里有两个问题 - 让您的代码编译,并从 GHC 获得更好的错误消息。如果您 post 更多代码,我们可以在第一个方面提供更多帮助。
如果您不使用 surfDim
的类型签名,您会得到更有用的错误吗?
V2 CInt
和 V2 (V2 CInt)
都不是可能的类型。你需要像 IO (V2 CInt)
这样的东西来满足 MonadIO m
。
GHC 尝试为 m
选择一个类型,在 V2 CInt
类型 sig 的指导下,并决定 m ~ V2
。不幸的是,这个选择并没有产生有用的错误信息。如果您使用建议的类型 sig 作为 "Actual type",我相信 GHC 将深入到类型检查过程中,以注意到没有实例 MonadIO V2
,正如您指出的那样。
我不知道是否有可能让 GHC 始终如一地就此类事情提供更好的建议。当我被类型错误难倒时,我喜欢尝试添加更多类型信号或删除一些。通常有不同的错误消息,对我来说,一个可能比另一个更有意义。
没有。您 运行 与类型检查器在报告错误消息之前尽可能统一的趋势相冲突。在这种情况下,类型检查器认为,"Oh, this expression has type m something
, and I want a V2 something
. So m
must be V2
." 它推迟到稍后检查 m = V2
是否满足 MonadIO
约束。在它到达那里之前,它查看了顶级类型,并意识到它不能统一 V2 CInt
和 CInt
,所以它在检查 V2
是否是一个 monad 之前就失败了.
作为一个人,您可能会通过支持和质疑您的哪些假设是错误的来回应错误。类型检查器根本不这样做。相反,它假设它的所有假设都很好,直到无法继续进行为止。然后它抱怨最后一步。到那时它已经掉进了一些奇怪的兔子洞是相当普遍的,这就是为什么 Haskell 类型错误是出了名的糟糕,尤其是当涉及类型 类 时。
现在,这是真正的错误。您需要计算 IO
monad(或 MonadIO
的其他实例)中的维度。这意味着你需要做:
surfDim <- SDL.surfaceDimensions surfIn
在一些适当的 do
块中。你不能把它变成一个普通的方程式。