当一个不匹配时,为什么我会收到 'Overlapping instances' 错误?
Why am I getting 'Overlapping instances' error when one doesn't match?
我正在尝试允许在我的免费 monad 中嵌入状态 monad;这是我的简单尝试:
{-# language FlexibleInstances, MultiParamTypeClasses #-}
module Main where
import Control.Monad.Free
import Control.Monad.State
import Data.Bifunctor
data Toy state next =
Output String next
| LiftState (state -> (next, state))
| Done
instance Functor (Toy s) where
fmap f (Output str next) = Output str $ f next
fmap f (LiftState stateF) = LiftState (first f . stateF)
fmap f Done = Done
instance MonadState s (Free (Toy s)) where
state = overState
overState :: (s -> (a, s)) -> Free (Toy s) a
overState = liftF . LiftState
output :: Show a => a -> Free (Toy s) ()
output x = liftF $ Output (show x) ()
done :: Free (Toy s) r
done = liftF Done
program :: Free (Toy Int) ()
program = do
start <- get
output start
modify ((+10) :: (Int -> Int))
end <- get
output end
done
interpret :: (Show r) => Free (Toy s) r -> s -> IO ()
interpret (Free (LiftState stateF)) s = let (next, newS) = stateF s
in interpret next newS
interpret (Free (Output str next)) s = print str >> interpret next s
interpret (Free Done) s = return ()
interpret (Pure x) s = print x
main :: IO ()
main = interpret program (5 :: Int)
我收到错误:
• Overlapping instances for MonadState Int (Free (Toy Int))
arising from a use of ‘get’
Matching instances:
instance [safe] (Functor m, MonadState s m) =>
MonadState s (Free m)
-- Defined in ‘Control.Monad.Free’
instance MonadState s (Free (Toy s))
-- Defined at app/Main.hs:18:10
• In a stmt of a 'do' block: start <- get
In the expression:
do { start <- get;
output start;
modify ((+ 10) :: Int -> Int);
end <- get;
.... }
In an equation for ‘program’:
program
= do { start <- get;
output start;
modify ((+ 10) :: Int -> Int);
.... }
尽我所能;它正在尝试应用此实例:
(Functor m, MonadState s m) => MonadState s (Free m)
来自
free package here;但是在这种情况下,它必须匹配 Free (Toy s)
并且没有按要求匹配 MonadState s (Toy s)
所以我不明白为什么它认为它适用。
如果删除我的实例定义,我会得到:
• No instance for (MonadState Int (Toy Int))
arising from a use of ‘modify’
这支持了我的想法,即另一个实例实际上并不适用;我怎样才能使用我指定的实例来编译它?你能解释为什么会这样吗?是因为 FlexibleInstances
被使用了吗?
谢谢!
实例上下文((Functor m, MonadState s m)
位)在选择实例时被忽略。这是为了防止编译器不得不进行可能代价高昂的回溯搜索来选择实例。因此,如果两个实例适用,而一个实例仅由于实例上下文而被排除,就像您的情况一样,那就是重叠。
这是 mtl 设计中一个不幸的部分,我认为每个 Haskell 程序员都在某些时候遇到过。修复的选择不多;通常你添加一个新类型并给出你的实例,如
newtype FreeToy s a = FreeToy (Free (Toy s) a)
instance MonadState s (FreeToy s) where -- ...
我正在尝试允许在我的免费 monad 中嵌入状态 monad;这是我的简单尝试:
{-# language FlexibleInstances, MultiParamTypeClasses #-}
module Main where
import Control.Monad.Free
import Control.Monad.State
import Data.Bifunctor
data Toy state next =
Output String next
| LiftState (state -> (next, state))
| Done
instance Functor (Toy s) where
fmap f (Output str next) = Output str $ f next
fmap f (LiftState stateF) = LiftState (first f . stateF)
fmap f Done = Done
instance MonadState s (Free (Toy s)) where
state = overState
overState :: (s -> (a, s)) -> Free (Toy s) a
overState = liftF . LiftState
output :: Show a => a -> Free (Toy s) ()
output x = liftF $ Output (show x) ()
done :: Free (Toy s) r
done = liftF Done
program :: Free (Toy Int) ()
program = do
start <- get
output start
modify ((+10) :: (Int -> Int))
end <- get
output end
done
interpret :: (Show r) => Free (Toy s) r -> s -> IO ()
interpret (Free (LiftState stateF)) s = let (next, newS) = stateF s
in interpret next newS
interpret (Free (Output str next)) s = print str >> interpret next s
interpret (Free Done) s = return ()
interpret (Pure x) s = print x
main :: IO ()
main = interpret program (5 :: Int)
我收到错误:
• Overlapping instances for MonadState Int (Free (Toy Int))
arising from a use of ‘get’
Matching instances:
instance [safe] (Functor m, MonadState s m) =>
MonadState s (Free m)
-- Defined in ‘Control.Monad.Free’
instance MonadState s (Free (Toy s))
-- Defined at app/Main.hs:18:10
• In a stmt of a 'do' block: start <- get
In the expression:
do { start <- get;
output start;
modify ((+ 10) :: Int -> Int);
end <- get;
.... }
In an equation for ‘program’:
program
= do { start <- get;
output start;
modify ((+ 10) :: Int -> Int);
.... }
尽我所能;它正在尝试应用此实例:
(Functor m, MonadState s m) => MonadState s (Free m)
来自
free package here;但是在这种情况下,它必须匹配 Free (Toy s)
并且没有按要求匹配 MonadState s (Toy s)
所以我不明白为什么它认为它适用。
如果删除我的实例定义,我会得到:
• No instance for (MonadState Int (Toy Int))
arising from a use of ‘modify’
这支持了我的想法,即另一个实例实际上并不适用;我怎样才能使用我指定的实例来编译它?你能解释为什么会这样吗?是因为 FlexibleInstances
被使用了吗?
谢谢!
实例上下文((Functor m, MonadState s m)
位)在选择实例时被忽略。这是为了防止编译器不得不进行可能代价高昂的回溯搜索来选择实例。因此,如果两个实例适用,而一个实例仅由于实例上下文而被排除,就像您的情况一样,那就是重叠。
这是 mtl 设计中一个不幸的部分,我认为每个 Haskell 程序员都在某些时候遇到过。修复的选择不多;通常你添加一个新类型并给出你的实例,如
newtype FreeToy s a = FreeToy (Free (Toy s) a)
instance MonadState s (FreeToy s) where -- ...