我正在努力更好地理解 Monads,我目前正在研究 Write Monadhttp://learnyouahaskell.com/for-a-few-monads-more#writer中的 Write Monad
我不明白它看似由兩種型別組成的型別宣告,也不明白它的型別約束。
在示例中,他們指定:
newtype Writer w a = Writer { runWriter :: (a, w) }
instance (Monoid w) => Monad (Writer w) where
return x = Writer (x, mempty)
(Writer (x,v)) >>= f = let (Writer (y, v')) = f x in Writer (y, v `mappend` v')
在行動中,它看起來像這樣:
ghci> runWriter (return 3 :: Writer String Int)
(3,"")
ghci> runWriter (return 3 :: Writer (Sum Int) Int)
(3,Sum {getSum = 0})
ghci> runWriter (return 3 :: Writer (Product Int) Int)
(3,Product {getProduct = 1})
但我想知道為什么它回傳Writer String Int而不是這些元素的元組?
我可以制作一個會回傳的 Monad 型別(例如 Writer2)Writer String Int Float 嗎?
此外,它讓我感到困惑,為什么實體化只需要(Monoid w) => Monad (Writer w)而不是(Monoid w a) => Monad (Writer w a). 以及為什么沒有w在 Monad 系結和回傳方法中列出,就像a將包含在型別約束的型別簽名中(Num a) => ...這可能是因為我在這方面有一些概念上的缺陷。
uj5u.com熱心網友回復:
Writer String如果你用更具體的替換更通用的,它可能會幫助你混淆StringWriter:
newtype StringWriter a = StringWriter (a, String)
instance Monad StringWriter where
return x = StringWriter (x, "")
(StringWriter (x, v)) >>= f = let (StringWriter (y, v')) = f x
in StringWriter (y, v v')
但我想知道為什么它回傳
Writer String Int而不是這些元素的元組?
AWriter String Int只是表示元組的另一種方式(Int, String)。查看 的簽名runWriter,它從 a 轉換Writer String Int為(Int, String):
runWriter :: Writer w a -> (a, w)
和資料建構式Writer,它轉換成相反的方向:
(a, w) -> Writer w a
我可以制作一個
Writer2會回傳的 Monad 型別(例如)Writer String Int Float嗎?
我不確定你的意思是什么,但對于 monad 來說,它必須適用于所有型別,所以當你宣告 monad 實體時ain很重要。StringWriter a(令人困惑的是,你需要它但不要寫它:instance Monad StringWriter。)
此外,它讓我感到困惑,為什么實體化只需要
(Monoid w) => Monad (Writer w)而不是(Monoid w a) => Monad (Writer w a).
幾點:
Monoid w a沒有意義,因為Monoid型別類只有一個引數:class Semigroup a => Monoid a whereMonad (Writer w a)沒有意義,因為型別類的引數Monad不是型別,而是型別建構式(帶有一個引數)。這與Monoid采用具體型別(而不是一個引數的型別建構式)的型別類形成對比。也就是說,instance Monad StringWriter是正確的,但instance Monad (StringWriter Int)不是。請注意,這StringWriter Int是一個型別,但StringWriter它是一個帶有一個引數的型別建構式。
以及為什么沒有
w在 Monad 系結和return方法中列出,比如a將包含在型別約束的型別簽名中(Num a) => ...
它沒有列出,因為函式型別宣告沒有列出。您可以啟用InstanceSigs擴展并明確撰寫它們:
{-# LANGUAGE InstanceSigs #-}
instance (Monoid w) => Monad (Writer w) where
return :: (Monoid w) => a -> Writer w a
return x = Writer (x, mempty)
(>>=) :: (Monoid w) => Writer w a -> (a -> Writer w b) -> Writer w b
(Writer (x,v)) >>= f = let (Writer (y, v')) = f x
in Writer (y, v `mappend` v')
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/532469.html
上一篇:如何將多個值傳遞給一元函式
