我是 Haskell 的初學者。我知道該函式fmap接受兩個引數 ( (a->b) -> f a ->) 并回傳一個函子 ( f b),但我無法理解以下 lambda 運算式
*Main> :t \g x -> fmap ($) g x
\g x -> fmap ($) g x :: (t -> a -> b) -> t -> a -> b
函子在哪里?
順便說一句,我已經嘗試了幾個帶有不同括號的類似運算式,它們給出了不同的結果:
*Main> :t \g x -> fmap ($) (g x)
\g x -> fmap ($) (g x) :: Functor f => (t -> f (a -> b)) -> t -> f (a -> b)
*Main> :t \g x -> fmap $ g x
\g x -> fmap $ g x :: Functor f => (t -> a -> b) -> t -> f a -> f b
我不明白這個。
uj5u.com熱心網友回復:
從
\g x -> fmap ($) g x :: (t -> a -> b) -> t -> a -> b
我們有
g :: t -> a -> b
x :: t
fmap ($) g :: t -> a -> b
fmap ($) g x :: a -> b
要找到函子,只需將 的型別撰寫為 some和g的型別級應用程式即可。F XFX
我們有
t -> a -> b = (->) t (a -> b)
因此,F = (->) t和X = (a -> b)。
因此,該fmap呼叫在(->) t函子中起作用。我們需要將 tot -> a -> b視為a -> bfunctor 下“包裝”型別的值(->) t。
現在,我們有
($) :: (a->b) -> a -> b
-- which means
($) :: (a->b) -> (a -> b)
g :: F (a->b)
fmap ($) :: F (a->b) -> F (a->b)
fmap ($) g :: F (a->b)
-- i.e.
fmap ($) g :: t -> (a->b)
uj5u.com熱心網友回復:
首先,正如你所說,我們有
fmap :: Functor f
=> ( a -> b ) -> f a -> f b
($) :: (t->s) -> t -> s
g :: f a
~ f (t->s)
----------------------------------------- a ~ (t->s) ~ b
fmap ($) g :: f b
~ f (t->s)
然后將其應用于x... 但只有函式應用于引數:
fmap ($) g :: Functor f => f (t->s)
~ Functor ((->) c) => c -> (t->s)
x :: c
---------------------------------------------- f ~ ((->) c)
fmap ($) g x :: (t->s)
并且確實((->) c)是一個函子。所以對 an 的應用x是選擇一個特定的 Functor 型別,函式的 Functor。
把這一切放在一起,
-- g x
\g x -> fmap ($) g x :: (c -> (t->s)) -> c -> (t->s)
-- compare with
fmap ($) :: f (t->s) -> f (t->s) -- Functor (f ~ ((->) c)
fmap id :: f q -> f q
id :: r -> r
Indeed($)只是一個更專業的id, 和fmap id === id,由函子定律。由于所有額外的引數/實體化為其提供了更多背景關系,因此該型別變得更加專業化。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/359145.html
上一篇:<$>和<*>如何發音?
