[英]Haskell: Flaw in the description of applicative functor laws in the hackage Control.Applicative article?: it says Applicative determines Functor
我想我在Control.Applicative
的hackage文章中發現了一個漏洞。 作為應用仿函數法的描述,它說:
class Functor f => Applicative f where
帶應用程序的仿函數,提供嵌入純表達式(
pure
)的操作,以及序列計算並組合它們的結果(<*>
)。最小完整定義必須包括滿足以下法則的這些函數的實現:
身分
pure id <*> v = v
組成
pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
同態
pure f <*> pure x = pure (fx)
互換
u <*> pure y = pure ($ y) <*> u
(請注意,這並沒有說明fmap)並且它聲明這些法則確定了Functor
實例:
作為這些定律的結果,f的
Functor
實例將滿足fmap fx = pure f <*> x
我一開始以為這顯然是錯的。 也就是說,我猜一定存在一個類型構造t
滿足以下兩個條件:
t
是實現上述規則的Applicative
的實例,並且 instance (Functor t)
有兩種不同的實現instance (Functor t)
(即有兩個不同的函數fmap1, fmap2 :: (a->b) -> (t a->tb)
,滿足函子定律)。 如果(且僅當)上述內容正確,則必須重寫上述語句
f的Functor實例必須滿足
fmap fx = pure f <*> x
由於這些法律,這符合
Functor
法律。
這顯然是正確的, 無論我的猜測是否正確 。
我的問題是 : 我猜是正確的嗎? 是否有一個t
與所需的條件是什么?
以下是我自己在試圖回答這個問題時的想法。
如果我們僅僅是數學家對實際的Haskell編程不感興趣 ,我們可以很容易地肯定地回答這個問題。 事實上,
t = Identity
newtype Identity a = Identity {runIdentity :: a}
符合上面的要求1和2(事實上,幾乎任何事情都可以)。 實際上, Identity
是一個Functor
和Applicative
的實例,如Data.Functor.Identity
所定義。 (這滿足fmap f = (pure f <*>)
。)為了定義instance (Functor f)
另一個“實現” instance (Functor f)
,對於每個類型a
,Take,兩個函數
transf_a, tinv_a :: a -> a
這樣的
tinv_a . transf_a = id
(從理論上講 ,這很容易)。 現在定義
instance (Functor Identity) where
fmap (f :: a->b) = Identity . transf_b . f . tinv_a . runIdentity
這符合Functor
法則,如果有的話,它是與瑣碎的法則不同的實現
x :: a
f :: a -> b
這樣的
f x /= transf_b $ f $ tinv_a x
但是我們是否可以在Haskell中做到這一點並不明顯。 是這樣的:
class (Isom a) where
transf, tinv :: a -> a
instance (Isom a) where
transf = id
tinv = id
specialized instance (Isom Bool) where
transf = not
tinv = not
可能在Haskell?
我忘了寫一些非常重要的東西。 我認為Control.Applicative
是GHC基礎包的一部分,所以我也對我的問題的答案是否隨任何GHC語言擴展而改變感興趣,例如我還不了解的FlexibleInstances
或OverlappingInstances
。
Haskell中的任何類型最多只能有一個Functor
實例,所以你的猜測是不正確的:因為沒有類型t
可以存在兩個不同的instance (Functor t)
實現instance (Functor t)
。 見: http : //article.gmane.org/gmane.comp.lang.haskell.libraries/15384
它是a a -> a
類型的屬性,它只有兩個居民,即id :: a -> a
(定義為id x = x
)和bottom :: a -> a
定義為bottom = error "Infinite loop."
。
如果我們僅將第一種情況局限於“合理”,我們得出一個重要的數學定理,即至少有一個類型為forall a. forall b. (a -> b) -> fa -> fb
函數fmap
forall a. forall b. (a -> b) -> fa -> fb
forall a. forall b. (a -> b) -> fa -> fb
forall a. forall b. (a -> b) -> fa -> fb
滿足fmap id = id
和fmap f . fmap g = fmap (f . g)
fmap f . fmap g = fmap (f . g)
。
如果我們不這樣做,那么你是正確的,我們有一個案例,其中fmap = undefined
,另一個fmap = (<*>) . pure
fmap = (<*>) . pure
。 但那有點俗氣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.