Это вопрос об использовании классов типов в Haskell.
Я получаю сообщение об ошибке (ниже) при попытке скомпилировать код (ниже и при
https://github.com/chrisdew/haskell-sandbox/blob/master/not_working_but_clean.hs
).
Как кто-то, только изучающий Хаскелл, я пытался следовать советам GHC,
но я думаю, что причина в другом.
Я считаю, что проблема в том, что либо типа 'IO String', либо обычный
«String» может относиться к типу «lhello - >> lbracket», но GHC этого не делает
знать, что.
Проблема в том, что это не имеет значения, любой тип будет работать нормально.
Я разместил рабочую версию кода на
https://github.com/chrisdew/haskell-sandbox/blob/master/working_but_ugly.hs
, Это заменяет один из операторов - >> новым (не тип класса)
оператор '- >>>', который заставляет 'lhello - >> lbracket' иметь тип 'IO
Строка».
Является ли мой анализ правильным? Или здесь что-то еще происходит?
Есть ли способ сообщить GHC, какой тип 'lhello - >>
Брэкет 'не имеет значения, и это должно просто выбрать любой из
две возможности. Или, возможно, есть вариант ЯЗЫКА, который позволит
мне указать, что «последний объявленный соответствующий экземпляр класса выигрывает»
если что-то не решено.
Спасибо
Крис.
Ошибка:
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.