Skip to content

Instantly share code, notes, and snippets.

@fusion5
Last active April 15, 2020 07:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fusion5/cb1d098751a0d1cafce19c6194757bf1 to your computer and use it in GitHub Desktop.
Save fusion5/cb1d098751a0d1cafce19c6194757bf1 to your computer and use it in GitHub Desktop.
I want a function (doc) in a type class (Documentable) that works in several monads (M1, M2)
Test.hs:48:5: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘doc’
prevents the constraint ‘(Documentable (M2 a0))’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instance exist:
instance Documentable (M2 ()) -- Defined at Test.hs:31:10
• In a stmt of a 'do' block:
doc "Hello, this is a comment in monad M2"
In the expression:
do doc "Hello, this is a comment in monad M2"
m1_in_m2 $ do doc "Hello, this is a comment in monad M1"
In an equation for ‘foo’:
foo
= do doc "Hello, this is a comment in monad M2"
m1_in_m2 $ do doc "Hello, this is a comment in monad M1"
|
48 | doc "Hello, this is a comment in monad M2"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{-# Language TypeSynonymInstances #-}
{-# Language FlexibleInstances #-}
{-# Language FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Main where
import Control.Monad.Except
import Control.Monad.Trans.State
import Data.Sequence as S
data M1State = M1State
{ docs :: S.Seq String -- Sequence of strings
} deriving (Eq, Show)
type M1 a = StateT M1State (Except String) a
newtype M2 a = M2 { runM2 :: M1 a }
deriving (Monad)
instance Functor M2 where
fmap = liftM
instance Applicative M2 where
pure = return
(<*>) = ap
class Documentable a where
doc :: String -> a
instance Documentable (M2 ()) where
doc txt = do
M2 $ doc txt
instance Documentable (M1 ()) where
doc txt = do
modify (\s -> s { docs = docs s |> txt })
initialM1 = M1State { docs = S.empty }
runM1 = runExcept . flip execStateT initialM1
m1_in_m2 :: M1 a -> M2 a
m1_in_m2 = M2
foo :: M2 ()
foo = do
doc "Hello, this is a comment in monad M2"
m1_in_m2 $ do
doc "Hello, this is a comment in monad M1"
main = do
putStrLn "Hello World"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment