我正在閱讀 Bartosz Milewski 的“程式員類別理論”和 pg。164 他介紹了 Reader Functor 的自然變換:
newtype Reader e a = Reader (e -> a)
instance Functor (Reader e) where
fmap f (Reader g) = Reader (\x -> f (g x))
我很難理解這種轉換的型別簽名。
我最好的猜測是:
fmap :: (a -> b) -> (Reader e -> a) -> (Reader e -> b)
我很困惑,仿函式是在 Reader 部分應用的情況下宣告的Reader e,然后在第二行上f,g這是兩個函式引數。然后,有一個 lambda 運算式x。由于 沒有值x,我假設Reader(\x -> ....)lambda 運算式被部分應用。x是指一些外部價值嗎?在哪里e發揮作用?
那么,fmap 實體如何滿足fmap => (a->b) -> f a -> f b?
uj5u.com熱心網友回復:
首先,有兩個獨立的建構式,分別命名為Reader:
- kind 的型別建構式
Type -> Type -> Type - 型別為 的資料建構式
(a -> b) -> Reader a b。
Reader e是型別建構式的部分應用,用于通過 kind 獲取某些東西,Type -> Type適用于定義Functor實體。
Reader g是與 type 的值匹配的模式Reader e a,這意味著g系結到 type 的值e -> a。
為了構造一個型別的值Reader e b,我們需要構造一個型別的值e -> b。我們無法訪問b該函式回傳的型別值,但我們可以使用f :: a -> b. 因此,我們的型別函式e -> b將接受它的e引數,將其傳遞給g :: e -> a,然后我們會將結果傳遞給f。
Reader當您擴展為函式型別并以前綴(而不是中綴)順序撰寫它們時,會更容易看到。
fmap :: (a -> b) -> Reader e a -> Reader e b
-- by isomorphism of Reader e x and e -> x
:: (a -> b) -> (e -> a) -> (e -> b)
-- using prefix notation
:: (a -> b) -> ((->) e) a -> ((->) e) b
-- generalizing from a specific functor to an abstract functor
:: (a -> b) -> f a -> f b
f函子在哪里,(->) e或者Reader e我們正在定義它的實體。
或者可以說更簡單,
fmap :: (a -> b) -> Reader e a -> Reader e b
-- type constructor application is left-associative
:: (a -> b) -> (Reader e) a -> (Reader e) b
-- Reader e is the functor
:: (a -> b) -> f a -> f b
uj5u.com熱心網友回復:
不,這里f ~ Reader e,所以f a意味著Reader e a,因此:
fmap @(Reader e) :: (a -> b) -> Reader e a -> Reader e b
因此,它將使用函式f :: (a -> b)將 a 轉換Reader e a為 a Reader e b。
現在對于模式(Reader g),我們知道g有型別g :: e -> a,因此我們需要產生一個函式e -> b。我們可以通過創建一個將變數映射x到的函式來做到這一點g x,然后應用于f該結果,這樣\x -> f (g x)或更短f . g的具有 type f . g :: e -> b,從而滿足型別約束。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/528502.html
標籤:哈斯克尔
上一篇:簡單資料型別的未裝箱向量
