这是我们了解实例的功课,但是作为标题,我不知道“如何定义一个Log-instance(a,b),而a和b也是Log-instance”。
data FullLog = FullLog [String] deriving Show
instance Semigroup FullLog where
FullLog a <> FullLog b = FullLog (a ++ b)
instance Monoid FullLog where
mempty = FullLog []
instance Log FullLog where
logMsg x = FullLog [x]
-- *Main> fib 3 :: (Int, ReverseLog)
-- (3,ReverseLog ["fib 3","fib 1","fib 2","fib 0","fib 1"])
-- instance Log ReverseLog where
data ReverseLog = ReverseLog [String] deriving Show
instance Semigroup ReverseLog where
ReverseLog a <> ReverseLog b = ReverseLog (b ++ a)
instance Monoid ReverseLog where
mempty = ReverseLog []
instance Log ReverseLog where
logMsg x = ReverseLog [x]
-- *Main> fib 3 :: (Int, LastMsgLog)
-- (3,LastMsgLog (Just "fib 3"))
--instance Log LastMsgLog where
data LastMsgLog = LastMsgLog (Maybe String) deriving Show
instance Semigroup LastMsgLog where
LastMsgLog a <> LastMsgLog b = LastMsgLog (b)
instance Monoid LastMsgLog where
mempty = LastMsgLog (Nothing)
instance Log LastMsgLog where
logMsg x = LastMsgLog (Just x)
-- *Main> fib 3 :: (Int, CountLog)
-- (3,CountLog 5)
--instance Log CountLog where
data CountLog = CountLog Int deriving Show
instance Semigroup CountLog where
CountLog a <> CountLog b = CountLog (a+b)
instance Monoid CountLog where
mempty = CountLog 0
instance Log CountLog where
logMsg x = CountLog 1
我已经完成4个Log实例:FullLog,ReverseLog,LastMsgLog和CountLog, 现在,我需要定义Log-instance(a,b),其中a和b可以是FullLog,ReverseLog,LastMsgLog和CountLog中的任何一个。
我尝试直接定义Log (a,b)
,错误就像Not in scope: data constructor ‘Log’
一样。
因此,我试图像上面一样定义类型MixLog
data MixLog = MixLog (a, b) deriving Show
instance MixLog :: (Log a, Log b) => Log (a, b) where
Log ( a, b) <> Log ( c, d ) = Log (a <> c, b <> d)
而且还有error: parse error on input ‘::’
所以现在我很困惑,如何进行类型约束?
谢谢!
答案 0 :(得分:2)
如果要将MixLog
设为Log
的实例,则可以这样实现:
data MixLog a b = MixLog (a, b)
instance (Log a, Log b) => Log (MixLog a b) where
logMsg x = MixLog (logMsg x, logMsg x)
因此,您需要在a
类型构造函数中指定类型参数b
和MixLog
,此外,我们用logMsg :: Log c => String -> c
对象定义MixLog
函数,因此我们用2元组构造一个MixLog
,其中两个元素都是logMsg x
调用的结果(或者我们可以用不同的方式实现)。
不过,您可以省略MixLog
数据构造函数,并将其实现为:
instance (Log a, Log b) => Log (a,b) where
logMsg x = (logMsg x, logMsg x)
2元组没有什么特别的,因此我们可以使用其类型构造函数和数据构造函数。