2015-08-29 31 views
6

我已經定義的類型X作爲爲什麼我不使用`>> =`而沒有顯式或隱式的定義?

newtype X i o = X { runX :: Int -> i -> IO o } 

我已經做的FunctorApplicativeMonad一個實例與

instance Functor (X i) where 
    fmap f a = X $ \ i o -> liftA f $ runX a i o 

instance Applicative (X i) where 
    pure x = X $ \ _ _ -> return x 
    a <*> b = X $ \ i o -> liftA2 (<*>) (runX a i o) (runX b i o) 

instance Monad (X i) where 
    return = pure 
    a >> b = X $ \ i o -> runX a i o >> runX b i o 

正如你可能會說,我一直,thusfar,無法來定義爲>>=,所以排除了它。我預計這會在編譯時出錯,但事實上,它所做的只是提出警告。很好,所以它不檢查一個類的所有方法是否被定義,但當然我實際上不能使用使用>>=。不,再次錯了。令我非常驚訝的是,GHCi愉快地評估let x = pure 5 >>= pureControl.Monad不會導出>>=的默認定義,我當然還沒有定義一個,那麼這怎麼可能?

+1

我不能讓你的'Functor'實例進行類型檢查。它抱怨說它不能與'IO(f0 a)'與'i0 - > IO o0'匹配。 –

+1

發佈的代碼不會編譯(例如它應該是'fmap'定義中的'runX a i o')。也許你在這裏粘貼了一個錯誤的版本? – duplode

+0

這仍然不適用於我,但拿出'liftA'。 –

回答

9

鑑於你糾正的定義,如果我嘗試定義,然後用x,我得到預期的運行時異常:

λ> let x = pure 5 >>= pure :: X Int Int 
λ> runX x 5 5 
*** Exception: foo.hs:12:10-20: No instance nor default method for class operation GHC.Base.>>= 

有兩個可能的原因,你不會看到。

第一個是你剛纔跑let,但從來沒有嘗試過評估結果。由於Haskell是懶惰的,let x = ...實際上並沒有做任何事情。 x只會在您實際嘗試使用它時纔會被評估(即,即runX),因此您可能會遇到錯誤。

另一種可能性是,你使用的let沒有指定類型:

λ> let x = pure 5 >>= pure 
λ> x 
5 

這裏,x是在單子m它使用多態。要打印一些像這樣的多態性字詞有用的東西,ghci默認mIO,它可以正常工作並給你5,但不會告訴你任何關於你的自定義monad的有用信息。

+0

這也是我所期望的,但都不是這樣。我在這裏使用了一種高度限制的函數,而不是'pure's,我試着簡單地將'x'插入到GHCi中。它成功沒有錯誤。然而,我使用的'IO'實際上代表了創建一個WX小部件,當我試圖評估我得到一個SegFault時。任何關於wxHaskell可能導致這種情況的想法? – Kwarrtz

+0

@Kwarrtz:這將它變成另一個問題,我不知道我能提供多少幫助。我認爲你最好單獨詢問具體的案例細節。 –

相關問題