请帮助我理解以下定义:
newtype Writer w a = Writer { runWriter :: (a,w) }
instance (Monoid w) => Monad (Writer w) where
return a = Writer (a,mempty)
(Writer (a,w)) >>= f = let (a',w') = runWriter $ f a in Writer (a',w `mappend` w')
为什么runWriter被声明为
runWriter :: (a,w)
当它的实际类型是:
runWriter :: Writer w a -> (a, w)
一旦我尝试使用ghci,我意识到这必须是一些隐含的参数,因为必须确定类型“a”,但这里究竟发生了什么?
答案 0 :(得分:8)
因为runWriter
是Writer
上的记录字段访问者。它实际上几乎相当于
runWriter (Writer x) = x
Haskell只有记录提供
例如
someWriter{runWriter = (new, values)} -- Returns a new Writer.
如果它有所帮助,可以将它想象成最粗糙的“功能性吸气剂”。对于1字段,这可能看起来并不十分重要,您可以始终模式匹配,但是当您有5个字段时,记录+功能更新非常有用。有关更深入的解释,请参阅LYAH。
答案 1 :(得分:0)
另一种看待它的方法:你可以想象像这样定义2元组(如果特殊的(,)
语法不是一个特殊的内置语法)
data (,) a b = (,) { fst :: a, snd :: b }
然后fst
和snd
会表现正常:
fst :: (a,b) -> a
fst (x,y) = x
(例如newtype
适用于只有一个值字段的类型。对于包含多个字段的类型,需要data
。)