
This is a question about the use of type classes in Haskell. I get an error (below) when trying to compile the code (below and at https://github.com/chrisdew/haskell-sandbox/blob/master/not_working_but_clea... ). As someone just learning Haskell, I have tried following GHC's advice, but I think the cause is different. I believe the problem is that either of the types 'IO String' or plain 'String' could be the type of 'lhello ->> lbracket', but GHC doesn't know which. The problem is that it doesn't matter, either type would work fine. I have posted a working version of the code at https://github.com/chrisdew/haskell-sandbox/blob/master/working_but_ugly.hs . This replaces one of the ->> operators with a new (non type class) operator '->>>' which forces 'lhello ->> lbracket' to be of type 'IO String'. * Is my analysis correct? Or is there something else going on here? * Is there any way of informing GHC what the type of 'lhello ->> lbracket' doen't matter and that is should just chose either of the two possibilities. Or perhaps theres a LANGUAGE option which will let me specify that 'lastest declared matching instance of the class wins' if anything is undecided. Thanks, Chris. Error: chris@chris-linux-desktop:~/nonworkspace/haskell-sandbox$ ghc not_working_but_clean.hs not_working_but_clean.hs:40:16: No instance for (Stream (IO String) (IO String) (IO String) d) arising from a use of `->>' at not_working_but_clean.hs:40:16-34 Possible fix: add an instance declaration for (Stream (IO String) (IO String) (IO String) d) In the first argument of `(->>)', namely `lhello ->> lbracket' In the second argument of `($)', namely `lhello ->> lbracket ->> putStrLn' In a stmt of a 'do' expression: forkIO $ lhello ->> lbracket ->> putStrLn not_working_but_clean.hs:40:16: No instance for (Stream d String (IO ()) (IO ())) arising from a use of `->>' at not_working_but_clean.hs:40:16-47 Possible fix: add an instance declaration for (Stream d String (IO ()) (IO ())) In the second argument of `($)', namely `lhello ->> lbracket ->> putStrLn' In a stmt of a 'do' expression: forkIO $ lhello ->> lbracket ->> putStrLn In the expression: do { forkIO $ (bracket $ hello) ->> putStrLn; forkIO $ lhello ->> lbracket ->> putStrLn; forkIO $ bracket hello ->> putStrLn; forkIO $ lbracket lhello ->> putStrLn; .... } not_working_but_clean.hs: {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, TypeSynonymInstances, OverlappingInstances #-} {-# OPTIONS_GHC #-} module Main ( main ) where import Control.Concurrent (forkIO, MVar, newEmptyMVar, putMVar, takeMVar, ThreadId, threadDelay) import Control.Monad (forever, liftM) class Stream a b c d where (->>) :: a -> (b -> c) -> d instance Stream (IO d) d (IO c) (IO c) where f ->> g = f >>= g instance Stream d d (IO c) (IO c) where f ->> g = g f instance Stream d d c c where x ->> y = y $ x -- This simply wraps a string in brackets. bracket :: String -> String bracket x = "(" ++ x ++ ")" lbracket :: IO String -> IO String lbracket x = liftM bracket x hello :: String hello = "Hello World!" lhello :: IO String lhello = do return hello main :: IO () main = do forkIO $ (bracket $ hello) ->> putStrLn forkIO $ lhello ->> lbracket ->> putStrLn forkIO $ bracket hello ->> putStrLn forkIO $ lbracket lhello ->> putStrLn threadDelay 10000000 -- Sleep for at least 10 seconds before exiting. working_but_ugly.hs: {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, TypeSynonymInstances, OverlappingInstances #-} {-# OPTIONS_GHC #-} module Main ( main ) where import Control.Concurrent (forkIO, MVar, newEmptyMVar, putMVar, takeMVar, ThreadId, threadDelay) import Control.Monad (forever, liftM) class Stream a b c d where (->>) :: a -> (b -> c) -> d instance Stream (IO d) d (IO c) (IO c) where f ->> g = f >>= g instance Stream d d (IO c) (IO c) where f ->> g = g f instance Stream d d c c where x ->> y = y $ x x ->>> y = y $ x -- This simply wraps a string in brackets. bracket :: String -> String bracket x = "(" ++ x ++ ")" lbracket :: IO String -> IO String lbracket x = liftM bracket x hello :: String hello = "Hello World!" lhello :: IO String lhello = do return hello main :: IO () main = do forkIO $ (bracket $ hello) ->> putStrLn forkIO $ lhello ->>> lbracket ->> putStrLn forkIO $ bracket hello ->> putStrLn forkIO $ lbracket lhello ->> putStrLn threadDelay 10000000 -- Sleep for at least 10 seconds before exiting.