gpt4 book ai didi

haskell - 免费 Monad 的 MonadError 实例

转载 作者:行者123 更新时间:2023-12-02 16:39:04 26 4
gpt4 key购买 nike

我用 sum 数据类型创建了一个非常有用的 Free Monad。这抽象了对持久数据存储的访问:

data DataStoreF next = 
Create Asset ( String -> next)
| Read String ( Asset -> next)
| Update Asset ( Bool -> next)
| UpdateAll [Asset] ( Bool -> next)
| Delete Asset ( Bool -> next)
| [...] -- etc. etc.
| Error String

type DataStore = Free DataStoreF

我想让 DataStore 成为 MonadError 的实例,并将错误消息处理为 (Free (Error str)):

instance MonadError String DataStore where
throwError str = errorDS str
catchError (Free (ErrorDS str)) f = f str
catchError x _ = x

但是我遇到了重叠实例错误。

创建 DataStore monad 和 MonadError 实例的正确方法是什么?

最佳答案

Free 类型已经为所有 免费 monad 提供了一个 MonadError 实例:

instance (Functor m, MonadError e m) => MonadError e (Free m) where { ... }

当您编写type DataStore = ...时,您只是定义了一个类型别名,它基本上是一个类型级宏。 DataStore 类型的所有使用都将替换为其定义。这意味着使用 DataStore 与直接使用 Free DataStoreF 没有区别,因此当您这样做时:

instance MonadError String DataStore where { ... }

…你实际上正在这样做:

instance MonadError String (Free DataStoreF) where { ... }

...这与上面定义的实例冲突。

为了避免这种情况,您应该定义一个 newtype 来生成一个全新的类型,该类型可以拥有自己的实例,与 Free 上定义的实例无关。如果您使用 GeneralizedNewtypeDeriving 扩展,则可以避免使用单独的 newtype 所需的大量样板:

{-# LANGUAGE GeneralizedNewtypeDeriving -}

data DataStoreF next = ...

newtype DataStore a = DataStore (Free DataStoreF a)
deriving (Functor, Applicative, Monad)

instance MonadError String DataStore where { ... }

这应该避免重叠实例问题,而无需手动写出所有 FunctorApplicativeMonad 实例。

关于haskell - 免费 Monad 的 MonadError 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38798660/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com