haskell - 未将类型识别为变压器堆栈内的单子的关联类型
问题描述
我一般都在玩 OpenGL,特别是在使用名为 GPipe 的 Haskell 库。IO
我在底部有一个 monad 转换器堆栈,然后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
期望 aWindowParameters 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 ()
我做错了什么,但不知道是什么。
解决方案
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))
推荐阅读
- c# - 获取用户输入、成分和价格,并返回最便宜和最昂贵的
- php - 如何在窗口机器上运行 apache 服务器时运行 php 命令输入 STDIN 以接受输入
- javascript - 我可以在内联 js 中使用 defer 属性吗?
- spring-boot - CDATA问题有没有好的解决方案
- java - hibernate.org 捆绑“导入包”链接到 rt.jar 中的错误包 javax.transaction 而不是 jboss-transaction.jar
- curl - 来自海康威视门户站的流式视频 (DS-KV8102-IP)
- java - 我想在春季启动启动时在日志中打印项目版本和构建时间等构建信息
- c# - 使用 API 将消息发布到 slack
- python - 如何为列表中的几列填充数据框的值?
- c# - 读取串行数据