Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 为什么surfaceDimensions(显示)返回双封闭向量(V2 CInt)?_Haskell_Sdl - Fatal编程技术网

Haskell 为什么surfaceDimensions(显示)返回双封闭向量(V2 CInt)?

Haskell 为什么surfaceDimensions(显示)返回双封闭向量(V2 CInt)?,haskell,sdl,Haskell,Sdl,以下代码无法进行类型检查: 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.surfaceDime

以下代码无法进行类型检查:

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
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

由于V2对我来说是正确的,我不知道为什么会发生这种情况,但我最好的猜测是它满足了我的要求,我不知道为什么或者如何可能是由于我对V2的不完全理解。

这里有两个问题-编译代码,以及从GHC获得更好的错误消息。如果您发布更多的代码,我们可以在第一个方面提供更多帮助

如果您为surfDim保留了类型签名,是否会出现更有用的错误

V2 CInt和V2 CInt都不是可能的类型。你需要像IO V2 CInt这样的东西来满足MonadIO m

GHC试图在V2 CInt type sig的指导下为m选择一种类型,并决定m~V2。不幸的是,这个选择并没有产生有用的错误消息。如果您使用sig in建议的类型作为实际类型,我相信GHC将深入到类型检查过程中,注意到没有MonadIO V2实例,正如您所指出的


我不知道是否有可能让GHC就这类事情持续提供更好的建议。当我被一个类型错误难倒时,我喜欢尝试添加更多的类型sig或删除一些类型sig。通常会有不同的错误消息,其中一条对我来说可能比另一条更有意义。

事实并非如此。您正在与类型检查器在报告错误消息之前尽可能统一的趋势相冲突。在这种情况下,类型检查器认为,哦,这个表达式的类型是m,我想要一个V2。所以m必须是V2。它推迟到稍后检查m=V2是否满足MonadIO约束。在它到达之前,它查看顶级类型内部,并意识到它无法将V2 CInt与CInt统一起来,因此它在检查V2是否是monad之前就失败了

作为一个人,你可能会通过支持和质疑你的哪些假设是错误的来回应错误。类型检查器根本不这样做。相反,它假设所有的假设都是正确的,直到无法继续。然后它抱怨最后一步。这是相当常见的,到那时它已经进入了一个奇怪的兔子洞,这就是为什么Haskell类型错误是出了名的糟糕,特别是当这里涉及到类型类时

现在,这里是真正的错误。您需要计算IO monad或其他MonadIO实例中的维度。这意味着您需要执行以下操作:

surfDim <- SDL.surfaceDimensions surfIn

在一些适当的块中。你不能把它变成一个普通的等式。

有趣的是,我知道我可能是因为缺少MonadIO或任何嵌入结果的monad而把类型弄错了,但我想我已经太依赖类型检查器了,以至于无法告诉我在这种特殊情况下我的类型应该是什么。我以后会尽量记住统一。@bbarker,不幸的是,对于类型检查器来说,要找出你告诉它的那些相互矛盾的事情是错的并不是那么容易。安排能够回溯以调查类型错误似乎非常昂贵。看看是否有某种方法可以以正常的人类可读格式将一定数量的类型检查器历史显示为in-ddump tc trace,这将是一件有趣的事情。听起来很难。随着错误的发展,我想我在其他非主流语言中看到了更糟糕的情况,我可以想象自己会毫不费力地适应这种情况。@bbarker:当你遇到类型错误时,在这里和那里添加类型注释有助于缩小期望和编译器推断的差异。随着时间的推移,你会产生一种直觉,“当我看到这个错误时,我可能犯了这种错误”。
surfDim <- SDL.surfaceDimensions surfIn