这是关于在Haskell中使用类型类的问题。
我在尝试编译代码时遇到错误(下面)(下面和下面) https://github.com/chrisdew/haskell-sandbox/blob/master/not_working_but_clean.hs )。
作为刚刚学习Haskell的人,我尝试过遵循GHC的建议, 但我认为原因是不同的。
我认为问题在于“IO String”类型或普通类型 'String'可以是'lhello - >>的类型lbracket',但GHC没有 知道哪个。
问题在于无关紧要,任何一种类型都可以正常工作。
我已经发布了代码的工作版本 https://github.com/chrisdew/haskell-sandbox/blob/master/working_but_ugly.hs 。这取代了 - >>之一具有新(非类型类)的运算符 运营商' - >>>'强迫'lhello - >> lbracket'属于'IO 字符串”
我的分析是否正确?或者还有其他事情发生在这里吗?
有没有办法通知GHC'lhello - >>的类型是什么? lbracket'并不重要,那应该只选择其中之一 两种可能性。或者也许是一个LANGUAGE选项 我指定'最新声明的匹配的类实例获胜' 如果有什么不确定的话。
谢谢,
克里斯。
错误:
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.
答案 0 :(得分:4)
不,没有办法让GHC翻转硬币并选择一个。
所有实例的类型'c'与类型'd'相同,因此您可以省略类型'd'并在定义Stream时重用类型'c'。
instance Stream d d (IO c) (IO c) where
f ->> g = g f
instance Stream d d c c where
x ->> y = y $ x
以上是相同的。 “g f”和“y $ x”是相同的。那么为什么两个不同的实例呢?