Не распознавая тип как связанный тип монады внутри стека трансформаторов - PullRequest
0 голосов
/ 11 июня 2018

Я играю с OpenGL в целом и с библиотекой Haskell под названием GPipe в частности.У меня есть стек монадных преобразователей с IO внизу, затем ContextT преобразователь из библиотеки, затем StateT, потому что требуется какое-то состояние, и, наконец, newtype Processor, потому что простой type вызовет ужасную ошибку.сообщения для такого стека.Это общая идея.Однако приведенный ниже код не выполняет проверку типов:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where

import Control.Lens
import Control.Monad.State
import Control.Monad.Trans
import Control.Monad.Except

import qualified "GPipe" Graphics.GPipe as GP
import qualified "GPipe-GLFW" Graphics.GPipe.Context.GLFW as GLFW

---- State and Processor types ----

class ArtState os as | as -> os where
    event :: GP.ContextHandler ctx => as -> Processor ctx os (as, Maybe e)
    present :: GP.ContextHandler ctx => as -> Processor ctx os as
    window :: Lens' as (WindowType os)

data ProgramState = ProgramState

newtype GP.ContextHandler ctx => Processor ctx os a = Processor {
    runProcessor :: StateT ProgramState (GP.ContextT ctx os IO) a
}

---- MenuArt things ----

type WindowType os = GP.Window os GP.RGBFloat GP.Depth

data MenuArt os = MenuArt {
    _maWindow :: WindowType os
}

makeLenses ''MenuArt

instance ArtState os (MenuArt os) where
    event ms = Processor $ return (ms, Nothing)
    present ms = Processor $ return ms
    window = maWindow

initMenuArt :: (ArtState os a, GP.ContextHandler ctx) =>
       Maybe a 
    -> Processor ctx os (Either String (MenuArt os))
initMenuArt Nothing = Processor $ do
    win <- lift $ GP.newWindow (GP.WindowFormatColorDepth GP.RGB8 GP.Depth16)
                               (GLFW.defaultWindowConfig "foobar")
    return $ Right $ MenuArt {
        _maWindow = win
    }
initMenuArt (Just from) = Processor $ do
    return $ Right $ MenuArt {
        _maWindow = from ^. window
    }

---- events ----

data UserEvent = CloseWindow

Сообщение об ошибке выглядит следующим образом:

/tmp/testing/app/Main.hs:49:33: error:
    • Couldn't match expected type ‘GP.WindowParameters ctx’
                  with actual type ‘GLFW.WindowConfig’
    • In the second argument of ‘GP.newWindow’, namely
        ‘(GLFW.defaultWindowConfig "foobar")’
      In the second argument of ‘($)’, namely
        ‘GP.newWindow
           (GP.WindowFormatColorDepth GP.RGB8 GP.Depth16)
           (GLFW.defaultWindowConfig "foobar")’
      In a stmt of a 'do' block:
        win <- lift
                 $ GP.newWindow
                     (GP.WindowFormatColorDepth GP.RGB8 GP.Depth16)
                     (GLFW.defaultWindowConfig "foobar")
    • Relevant bindings include
        initMenuArt :: Maybe a
                       -> Processor ctx os (Either String (MenuArt os))
          (bound at app/Main.hs:47:1)
   |
49 |                                (GLFW.defaultWindowConfig "foobar")
   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Насколько я понял, newWindow ожидает WindowParameters ctxв качестве второго аргумента, который является ассоциированным типом для класса ContextHandler.Но компилятор не видит, что GLFW.WindowConfig является WindowParameters для этого стека по какой-то причине.Выбрасывание StateT и Processor из стека (как в учебнике, через который я работаю) работает, это компилирует:

main :: IO ()
main = do
  GP.runContextT GLFW.defaultHandleConfig $ do
    win <- GP.newWindow (GP.WindowFormatColor GP.RGB8) (GLFW.defaultWindowConfig "foobar")
    return ()
  return ()

Я делаю что-то не так, но не могу понятьчто.

1 Ответ

0 голосов
/ 11 июня 2018

initMenuArt использует GLFW.defaultWindowConfig, что является функцией GLFW.

GPipe определяет интерфейс, параметризованный типом ctx, а GPipe-GLFW реализует этот интерфейс путем создания экземпляра ctxс GLFW.Handle.

Таким образом initMenuArt должно быть соответственно специализировано:

initMenuArt
    :: (ArtState os a)
    => Maybe a 
    -> Processor GLFW.Handle os (Either String (MenuArt os))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...