不能将等式约束表示为自定义约束
Cannot represent equality constraint as a custom constraint
我有一个函数类型声明
f :: MonadHandler m => SqlPersistT m ()
我想转换成
f :: MonadHandlerDB m => m ()
我尝试了所有我能想到的方法来定义约束 MonadHandlerDB,但无法得到它或函数类型声明来编译,例如:
class (forall a . (MonadHandler m, m ~ SqlPersistT a)) => MonadHandlerDB m
class MonadHandlerDB m
instance MonadHandler a => MonadHandlerDB (SqlPersistT a)
type MonadHandlerDB m = forall a . (MonadHandler a, m ~ SqlPersistT a)
type MonadHandlerDB = forall a . (MonadHandler a => m ~ SqlPersistT a)
type MonadHandlerDB m = forall a . (MonadHandler a => m ~ SqlPersistT a)
错误之一:
Couldn't match type `m' with `ReaderT backend0 m0
`m' is a rigid type variable bound by
the type signature for:
f:: forall (m :: * -> *).
MonadHandlerDB m =>
m ()
SqlPersistT 定义为
type SqlPersistT = ReaderT SqlBackend
如何表达这种约束?
我认为这实现了你想要的:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeSynonymInstances #-}
import Control.Monad.Trans.Reader (ReaderT (ReaderT))
import Database.Persist.Sql (SqlPersistT)
import Yesod.Core (MonadHandler)
f :: MonadHandlerDB m => m ()
f = undefined
class (MonadHandler (Sub m), m ~ SqlPersistT (Sub m)) => MonadHandlerDB m where
type Sub m :: * -> *
instance MonadHandler m => MonadHandlerDB (SqlPersistT m) where
type Sub (SqlPersistT m) = m
但是请注意,我认为这在实践中确实不太好用。它使 m
看起来好像是完全多态的,但实际上,它只能是 SqlPersistT
.
中的一些单子。
约束很强大,但我认为像这样的约束很可能会混淆其用户。
我有一个函数类型声明
f :: MonadHandler m => SqlPersistT m ()
我想转换成
f :: MonadHandlerDB m => m ()
我尝试了所有我能想到的方法来定义约束 MonadHandlerDB,但无法得到它或函数类型声明来编译,例如:
class (forall a . (MonadHandler m, m ~ SqlPersistT a)) => MonadHandlerDB m
class MonadHandlerDB m
instance MonadHandler a => MonadHandlerDB (SqlPersistT a)
type MonadHandlerDB m = forall a . (MonadHandler a, m ~ SqlPersistT a)
type MonadHandlerDB = forall a . (MonadHandler a => m ~ SqlPersistT a)
type MonadHandlerDB m = forall a . (MonadHandler a => m ~ SqlPersistT a)
错误之一:
Couldn't match type `m' with `ReaderT backend0 m0
`m' is a rigid type variable bound by
the type signature for:
f:: forall (m :: * -> *).
MonadHandlerDB m =>
m ()
SqlPersistT 定义为
type SqlPersistT = ReaderT SqlBackend
如何表达这种约束?
我认为这实现了你想要的:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeSynonymInstances #-}
import Control.Monad.Trans.Reader (ReaderT (ReaderT))
import Database.Persist.Sql (SqlPersistT)
import Yesod.Core (MonadHandler)
f :: MonadHandlerDB m => m ()
f = undefined
class (MonadHandler (Sub m), m ~ SqlPersistT (Sub m)) => MonadHandlerDB m where
type Sub m :: * -> *
instance MonadHandler m => MonadHandlerDB (SqlPersistT m) where
type Sub (SqlPersistT m) = m
但是请注意,我认为这在实践中确实不太好用。它使 m
看起来好像是完全多态的,但实际上,它只能是 SqlPersistT
.
约束很强大,但我认为像这样的约束很可能会混淆其用户。