Почему SurfaceDimensions (появляется), чтобы вернуть дважды заключенный вектор (V2 V2 CInt)? - PullRequest
0 голосов
/ 25 октября 2018

Следующий код не может проверить тип:

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 ).

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Это не так.Вы сталкиваетесь с тенденцией проверки типов объединяться настолько, насколько это возможно, прежде чем сообщать об ошибке.В этом случае средство проверки типов думает: «О, это выражение имеет тип m something, и я хочу V2 something. Поэтому m должно быть V2».Он откладывает до последующей проверки, что m = V2 удовлетворяет этому ограничению MonadIO.И прежде чем попасть туда, он заглядывает внутрь типа верхнего уровня и понимает, что он не может объединить V2 CInt с CInt, поэтому он не может до проверки, является ли V2 монадой.

Как человек, вы можете отреагировать на свою ошибку, сделав резервную копию и спросив, какое из ваших предположений было неверным.Проверка типов не делает этого вообще.Вместо этого он предполагает, что все его предположения были в порядке вплоть до того момента, когда было невозможно продолжить.Тогда он жалуется на самый последний шаг.Довольно часто к тому времени он проходил по какой-то странной кроличьей норе, поэтому ошибки типов на Хаскеле, как известно, очень плохие, особенно когда здесь задействованы классы типов, как здесь.

Теперь вот настоящая ошибка,Вам необходимо вычислить измерения в монаде IO (или в другом экземпляре MonadIO).Это означает, что вам нужно сделать:

surfDim <- SDL.surfaceDimensions surfIn

в некотором соответствующем блоке do.Вы не можете сделать это просто обычным уравнением.

0 голосов
/ 25 октября 2018

Здесь есть две проблемы - заставить ваш код компилироваться и получать лучшие сообщения об ошибках от GHC.Если вы опубликуете больше своего кода, мы можем помочь с первым.

Получите ли вы более полезную ошибку, если не указывать сигнатуру типа для surfDim?

Ни V2 CInt, ни V2 (V2 CInt) не являются возможными типами.Вам нужно что-то вроде IO (V2 CInt), чтобы удовлетворить MonadIO m.

GHC попытался выбрать тип для m, руководствуясь типом sig V2 CInt, и решил, что m ~ V2.К сожалению, этот выбор не привел к полезному сообщению об ошибке.Если вы используете тип sig in предлагает как «Фактический тип», я думаю, что GHC зайдет достаточно далеко в процесс проверки типов, чтобы заметить, что нет экземпляра MonadIO V2, как вы указываете.

У меня нетИдея, если возможно, чтобы GHC постоянно давал лучшие советы по этому поводу.Когда я нахожусь в тупике из-за ошибки типа, мне нравится пытаться добавить больше сигнатур типа или убрать их.Часто появляются разные сообщения об ошибках, и одно может иметь для меня больший смысл, чем другое.

...