我是 Haskell 的新手,正在學習 Functor、Applicative 和 Monad。
我檢查了Either來自 hackage的 Functor 實體的型別是:
data Either a b = Left a | Right b
instance Functor (Either a) where
fmap _ (Left x) = Left x
fmap f (Right y) = Right (f y)
我被要求為擴展Either呼叫做 Functor、Applicative、Monad 實體MyEither:
data MyEither a b = MyLeft a | MyRight b | Nothing
deriving (Eq, Show)
我的問題是:
1 如何Nothing在我的實體中擴展?
2 派生一定要寫在實體中嗎?
誰能給我一些提示?
uj5u.com熱心網友回復:
當您實作實體時,您不需要撰寫deriving. deriving用于在定義新型別時讓編譯器為您派生實體。
對于Nothing,模式匹配就可以了,并回傳Nothing為所有的執行FAM。你無能為力。
這是一個類似的例子,可以幫助你。
data Nope a = NopeDataJpg deriving (Eq, Show)
instance Functor Nope where
fmap _ _ = NopeDataJpg
instance Applicative Nope where
pure x = NopeDataJpg
_ <*> _ = NopeDataJpg
instance Monad Nope where
return = pure
_ >>= _ = NopeDataJpg
此外,這里有Functor,Applicative和Monad的實作Maybe在GHC。它們的處理Nothing方式與您需要為您的資料型別執行的操作非常相似。
uj5u.com熱心網友回復:
當你寫下你的實體時,首先明確寫出型別:
data MyEither a b = MyLeft a | MyRight b | MyNothing
deriving (Eq, Show)
instance Functor (MyEither a) where
-- fmap :: Functor f => (b -> c) -> f b -> f c
-- fmap :: (b -> c) -> MyEither a b -> MyEither a c
(我將MyNothing在這里使用以防止與Maybe's混淆Nothing)。
現在我們準備根據資料型別定義列舉所有可能性:
fmap bc (MyLeft aValue) = result where
-- bc :: b -> c
-- MyLeft aValue :: MyEither a b
-- result :: MyEither a c
.....
這里我們必須產生一個型別的值MyEither a c作為結果。這個函式bc在這里沒用,因為我們只能訪問aValue :: atype的值a:
MyLeft aValue :: MyEither a b
--------------------------------
aValue :: a
因此,我們在這里有兩種可能性:
result = MyLeft aValue這將構造一個新值,這次MyEither a c是由型別簽名確定的型別;或者result = ....
填滿點,并在 1. 和 2 之間進行選擇,完成本子句的定義,fmap bc (MyLeft aValue) = ...。(但請參閱本文底部的重要說明)
下一個可能性是
fmap bc (MyRight bValue) = ...
這次我們確實可以訪問 type 的值b,因此該函式bc可以派上用場,因為
bValue :: b
bc :: b -> c
-------------------------
bc bValue :: c
和
cValue :: c
--------------------------------
myRight cValue :: MyEither a c
因此,該條款的自然定義是
fmap bc (MyRight bValue) = MyRight cValue
where
cValue = ....
當然,與第一個條款中相同的第二個選項在技術上也是可能的。(再次,請參閱本文底部的重要說明)在這里使用MyLeft構造MyEither a c值當然是不可能的,因為我們完全無法訪問任何a型別的值......除了undefined.
現在只剩下一種可能性了,對于MyEither a b我們fmap必須處理的型別值,根據它的型別簽名(記住,fmap :: (b -> c) -> MyEither a b -> MyEither a c)。而那個價值是……
fmap bc MyNothing =
同樣,我們必須產生一個型別的值MyEither a c作為結果。這一次我們無法訪問任何型別為 noneb或 的值a。所以除了退貨別無他法……
.......
(undefined當然沒有用途)。完成定義。
我希望您現在能夠根據需要完成其他定義。
重要更新:上面提到的那些選擇實際上根本沒有選擇。如果我們所關心的只是制定適合型別的定義,那么這些可能性確實存在。但是, Functor 等實體也必須是合法的。例如函子定律是
fmap id === id
fmap (f . g) === fmap f . fmap g
在每種情況下,只有一種可能性不會違反法律。特別是,fmap id (MyLeft _) = MyNothing打破了第一函子定律。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/365263.html
上一篇:Haskell也許加法器沒有引數
下一篇:檢查對單元格的參考是否有效
