簡體   English   中英

Haskell:為什么'id'使這個函數不再是monadic?

[英]Haskell: why does 'id' make this function no longer monadic?

我試圖理解為什么在下面的序列的最后一行添加id會刪除monadic方面:

Prelude> :t id
id :: a -> a
Prelude> :t Control.Monad.liftM2
Control.Monad.liftM2
  :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
Prelude> :t  (==)
(==) :: Eq a => a -> a -> Bool
Prelude> :t Control.Monad.liftM2 (==)
Control.Monad.liftM2 (==)
  :: (Monad m, Eq a) => m a -> m a -> m Bool
Prelude> :t Control.Monad.liftM2 (==) id
Control.Monad.liftM2 (==) id :: Eq a => (a -> a) -> a -> Bool
Prelude>

如何添加id :: a -> a以最后一行的方式更改簽名?

您正在將類型修改為特定的Monad實例,即“函數閱讀器”monad( instance Monad ((->) a) )。

id :: a -> a並且您嘗試將其用作ma類型參數的參數,因此:

m a  ~  a -> a
m a  ~  (->) a a
m a  ~  ((->) a) a
m    ~  (->) a
a    ~  a

簽名的其余部分是:

m a -> m Bool

由於m ~ (->) a ,結果類型為:

(->) a a -> (->) a Bool
(a -> a) -> (a -> Bool)
(a -> a) -> a -> Bool

(加上Eq a使用== Eq a約束。)

這在pointfree代碼中很有用,特別是使用Applicative實例,因為您可以隱式地將函數的參數“擴展”到子計算:

nextThree = (,,) <$> (+ 1) <*> (+ 2) <*> (+ 3)
-- or
nextThree = liftA3 (,,) (+ 1) (+ 2) (+ 3)

nextThree 5 == (6, 7, 8)

uncurry' f = f <$> fst <*> snd
-- or
uncurry' f = liftA2 f fst snd

uncurry' (+) (1, 2) == 3

liftM2 (==)的簽名是(Monad m, Eq a) => ma -> ma -> m Bool 所以這意味着如果我們用id :: b -> b作為參數調用這個函數,那么它意味着mab -> b是相同的類型。

m ~ (->) b保持的事實不是問題,因為(->) rMonad一個實例,實際上在我們看到的GHC.Base源代碼中

 -- | @since 2.01 instance Monad ((->) r) where f >>= k = \\ r -> k (fr) r 

這只有m ~ (->) b才有意義。 這里箭頭(->)是一個類型構造函數, (->) aba -> b相同。

所以這意味着如果我們計算liftM2 (==) id的類型,我們得出以下結果:

liftM2 (==)    ::  m a     -> m a -> m Bool
            id :: (b -> b)
-------------------------------------------
m ~ (->) b, a ~ b

這意味着liftM2 (==) id的輸出類型是liftM2 (==) id :: (Monad m, Eq a) => ma -> m Bool ,但我們需要用我們的知識“專門化”這個獲得: ma(->) bab類型,所以:

   liftM2 (==) id :: (Monad m, Eq a) => m a -> m Bool
-> liftM2 (==) id :: (Monad m, Eq a) => (b -> a) -> (b -> Bool)
-> liftM2 (==) id :: Eq b => (b -> b) -> (b -> Bool)
-> liftM2 (==) id :: Eq b => (b -> b) -> b -> Bool

簡而言之,該函數仍然是“monadic”,雖然通過使用id ,您已經選擇了一個特定的monad,因此該函數不再適用於所有類型的monad,只適用於(->) r monad。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM