根據the Typeclassopedia(其它來源之一),Applicative
邏輯Monad
和Pointed
(因此Functor
)之間所屬的類型的類層次結構,所以我們非常有這樣的事情,如果Haskell的前奏是今天寫的:可以liftM與liftA不同嗎?
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Pointed f where
pure :: a -> f a
class Pointed f => Applicative f where
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
-- either the traditional bind operation
(>>=) :: (m a) -> (a -> m b) -> m b
-- or the join operation, which together with fmap is enough
join :: m (m a) -> m a
-- or both with mutual default definitions
f >>= x = join ((fmap f) x)
join x = x >>= id
-- with return replaced by the inherited pure
-- ignoring fail for the purposes of discussion
(如果這些默認的釋義是我從explanation at Wikipedia重新輸入,錯誤的是我自己的,但如果有錯誤,它至少在原則上可能的)
由於庫目前的定義,我們有:
liftA :: (Applicative f) => (a -> b) -> f a -> f b
liftM :: (Monad m) => (a -> b) -> m a -> m b
和:
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
ap :: (Monad m) => m (a -> b) -> m a -> m b
注意這些類型的每對之間的相似性。
我的問題是:liftM
(從liftA
不同)和ap
(從<*>
不同),只需將歷史現實Monad
不是設計時考慮Pointed
和Applicative
的結果?或者他們是否以某種其他行爲方式(可能對某些合法的Monad
定義)區別於僅需要Applicative
上下文的版本?
如果它們是不同的,你可以提供一組簡單的定義(服從的Monad
需要Applicative
Pointed
的法律,以及在Typeclassopedia描述Functor
定義和其他地方而不是由類型系統執行)針對liftA
和liftM
表現不同?
或者,如果它們不明顯,您是否可以使用這些相同的法律來證明它們的等價性?
好的,的確,對於某些類型,有多個Applicative實例和多個Monad實例。但是,在上面的定義下,pure/return實現將不得不在應用實例和Monad實例之間共享。這是否意味着,爲了滿足法律,<*>和ap必須是相同的?它看起來像你的例子依賴使用pure = repeat爲[]創建Applicative實例,但對於[] with return =([])仍然使用Prelude Monad實例? – 2009-10-28 04:45:34
我可能會錯過一些東西,但它不是真的,類型'forall a,b。 (a - > b) - > F a - > F b'確保爲'fmap'。例如,考慮'notmap f xs = zipWith($)(repeat(const。f $ head xs))xs'。 – 2011-05-02 11:54:06
@Apocalisp:只給出fmap的類型,你仍然可以擁有異國情調的成員。邊條件fmap id = id足以強制這個問題,我認爲你在'f'中加入的額外量詞是作弊的。 ;)Doug,儘管Functor的定義在給定法律時是唯一的,但適用法律足夠寬鬆以允許多個符合的定義。但是,按照慣例,給定類型的Monad和Applicative應該兼容。 – 2012-05-15 02:32:43