2015-04-02 95 views
9

在斯卡拉茲每個Monad實例都自動成爲Applicative的一個實例。我可以自動實現類嗎?

implicit val listInstance = new Monad[List] { 
    def point[A](a: => A) = List(a) 
    def bind[A, B](fa: List[A])(f: A => List[B]) = fa flatMap f 
} 

List(2) <*> List((x: Int) => x + 1) // Works! 

又如:Arrow自動成爲Profunctor

但是,在Haskell中,我必須一次又一次爲每個Monad提供一個Applicative的實例。

是否可以避免這個重複的工作?

+0

目前還沒有,AFAIK。你必須添加'實例Applicative M,其中pure = return; (<*>)= ap'。我相信我看到了一些關於autoderiving超類的討論,即實現'Monad'和'Functor'並隱式添加'Applicative',但尚未實現(再次AFAIK)。也許你可以編寫一些模板Haskell來掃描當前monad實例並自動生成應用程序。不過,我不確定這是可能的。 – chi 2015-04-02 14:31:31

回答

2

目前尚不可能,但如果您更改了現有的庫以支持此操作,那將是不可能的。開啓DefaultSignatures會讓你寫

class Applicative f where 
    pure :: a -> f a 
    (<*>) :: f (a -> b) -> f a -> f b 

    default pure :: Monad f => a -> f a 
    default (<*>) :: Monad f => f (a -> b) -> f a -> f b 
    pure = return 
    (<*>) = ap 

然後,一旦你已經實施instance Monad M where {- ... -},一個簡單的instance Applicative M(沒有where或方法的定義)將繼承這些默認的實現。我不知道爲什麼這沒有完成。

3

問題出現時,有兩個地方可以派生出Applicative實例。例如,假設m是類型a b,其中Arrow a。那麼這個定義中還有一個明顯的Applicative實例。編譯器應該使用哪一個?當然,它應該是相同的,但Haskell無法檢查這一點。通過讓我們寫出實例,Haskell至少迫使我們考慮定義的一致性。

如果你想,有個WrappedMonadControl.Applicative,它提供了所有明顯的情況下,用newtype包裝,但使用WrapMonadunwrapMonad所有的時間是不是有吸引力的要麼。

相關問題