小编Alt*_*r93的帖子

使用类型同义词定义实例

如果这已经被问过/回答过很多次了,我很抱歉——我很难确定问题的实际是什么,因此不知道要搜索什么。


本质上,我定义了一个类:

class (MonadIO m) => Logger m where ...
Run Code Online (Sandbox Code Playgroud)

然后我有一个类型(我想说类型同义词,但我不确定这是否是正确的“术语”):

type ResourceOpT r m a = StateT (ResourceCache r) m a
Run Code Online (Sandbox Code Playgroud)

为什么这个实例是完全有效的:

instance (MonadIO m) => Logger ( StateT s m )
Run Code Online (Sandbox Code Playgroud)

但不是这个(我想第一个更抽象/更可取,但我试图理解为什么):

instance (MonadIO m) => Logger ( ResourceOpT r m )
Run Code Online (Sandbox Code Playgroud)

根据我的定义,两者不应该是等效的ResourceOpT吗?具体来说,我得到的错误是:

  The type synonym 'ResourceOpT' should have 3 arguments, but has been given 2
  In the instance declaration for 'Logger (ResourceOpT r m)'
Run Code Online (Sandbox Code Playgroud)

我有一种感觉,我正在做的事情在概念上“应该”起作用,但要么我的语法错误,要么我遗漏了某些东西(可能是语言扩展),或者应该让它起作用。

无论如何,我很想得到您的意见并了解为什么这是错误的以及为什么我应该/不应该这样做。

提前致谢。

haskell types instance typeclass type-synonyms

5
推荐指数
0
解决办法
111
查看次数

monad 转换器的最佳实践:隐藏或不隐藏“liftIO”

我会在序言中说,我是一名 Haskell 程序员新手(多年来偶尔对其进行修改),但在 OOO 和命令式编程方面,我已经有好几年的时间了。我目前正在学习如何使用 monad 并通过使用 monad 转换器将它们组合起来(假设我已经找到了正确的术语)。


虽然我能够将事物组装/链接在一起,但我发现很难对什么是最好的方式和风格以及如何最好地组装/编写这些交互建立直觉。

具体来说,我很想知道使用 lift/liftIO 以及两者之间的任何风味的最佳实践(或至少是你的实践)是什么,以及是否有方法(和好处)隐藏它们,因为我发现它们相当“吵闹” 。

下面是一个示例片段,我将其放在一起来说明我的意思:

consumeRenderStageGL' :: RenderStage -> StateT RenderStageContext IO ()
consumeRenderStageGL' r = do 
    pushDebugGroupGL (name r)
    liftIO $ consumePrologueGL ( prologue r )
    liftIO $ consumeEpilogueGL ( epilogue r )
    consumeStreamGL   ( stream   r )
    liftIO $ popDebugGroupGL
Run Code Online (Sandbox Code Playgroud)

它调用的一些函数利用了状态 monad :

pushDebugGroupGL :: String -> StateT RenderStageContext IO ()
pushDebugGroupGL tag = do
    currentDebugMessageID <- gets debugMessageID
    liftIO $ GL.pushDebugGroup GL.DebugSourceApplication (GL.DebugMessageID currentDebugMessageID) tag
    modify (\fc …
Run Code Online (Sandbox Code Playgroud)

haskell monad-transformers

4
推荐指数
1
解决办法
378
查看次数

类型类与函数?

我目前正在尝试使用 typeclasses & 作为练习,能够登录各种上下文(即在 IO 上下文中打印到控制台)。我首先将我的Logger实现为一个由各种用于日志记录的函数组成的类型类,我的想法是我可以为 IO monad 定义一个实例,但为其他 monad 的上下文中的其他实现留出空间。

最终结果是:

-- |Class / wrapper for convenient use within another monad.
class Logger m where
    -- |Logs an error message /(prefixed with the '__[ERROR]__' tag)/
    logError    :: String -> m ()
 
    -- |Logs a warning message /(prefixed with the '__[WARNING]__' tag)/
    logWarning  :: String -> m ()

    -- |Logs a success message /(prefixed with the '__[SUCCESS]__' tag)/
    logSuccess  :: String -> m ()

    -- |Logs …
Run Code Online (Sandbox Code Playgroud)

haskell typeclass

4
推荐指数
1
解决办法
75
查看次数