Joh*_*ler 3 haskell typeclass overlapping-instances free-monad
我用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
Run Code Online (Sandbox Code Playgroud)
我想将错误消息DataStore的实例MonadError处理为(Free (Error str)):
instance MonadError String DataStore where
throwError str = errorDS str
catchError (Free (ErrorDS str)) f = f str
catchError x _ = x
Run Code Online (Sandbox Code Playgroud)
但我遇到了Overlapping Instances错误.
制作DataStore单子和实例的正确方法是MonadError什么?
该Free类型已经MonadError为所有免费monad 提供了一个实例:
instance (Functor m, MonadError e m) => MonadError e (Free m) where { ... }
Run Code Online (Sandbox Code Playgroud)
在编写时type DataStore = ...,您只是定义一个类型别名,它基本上是一个类型级别的宏.该DataStore类型的所有用途都将替换为其定义.这意味着使用DataStore与Free DataStoreF直接使用无法区分,因此当您执行此操作时:
instance MonadError String DataStore where { ... }
Run Code Online (Sandbox Code Playgroud)
......你实际上是这样做的:
instance MonadError String (Free DataStoreF) where { ... }
Run Code Online (Sandbox Code Playgroud)
......并且与上面定义的实例冲突.
为了避免这种情况,你应该定义一个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 { ... }
Run Code Online (Sandbox Code Playgroud)
这应该避免重叠实例的问题,而不需要写出所有Functor,Applicative和Monad手动实例.
| 归档时间: |
|
| 查看次数: |
198 次 |
| 最近记录: |