2012-11-09 134 views
1

我是新來的哈斯克爾,我試圖寫我的第一個哈斯克爾C庫。這是我第一次使用Foreign.C模塊。我迷失在實例中,並陷入困境。這就是我來了這麼遠:GHC - 沒有實例(Monad Ptr)

{-# LANGUAGE ForeignFunctionInterface #-} 

module Grep where 

import GHC.Ptr 
import Foreign.C.String 
import Data.List (isInfixOf) 

grep :: CString -> CString -> CString 
grep i s = do 
    ii <- peekCString i 
    ss <- peekCString s 
    g <- newCString (isInfixOf ii ss) 
    g 

foreign export ccall grep :: CString -> CString -> CString 

我收到以下錯誤:

PS C:\Users\GGuy\Source\haskell> ghc -c -O grep.hs 

grep.hs:11:9: 
    No instance for (Monad Ptr) 
    arising from a do statement 
    Possible fix: add an instance declaration for (Monad Ptr) 
    In a stmt of a 'do' block: ii <- (peekCString i) 
    In the expression: 
    do { ii <- (peekCString i); 
     ss <- peekCString s; 
     g <- newCString (isInfixOf ii ss); 
     g } 
    In an equation for `grep': 
    grep i s 
     = do { ii <- (peekCString i); 
      ss <- peekCString s; 
      g <- newCString (isInfixOf ii ss); 
      .... } 

grep.hs:11:16: 
    Couldn't match expected type `Ptr t0' with actual type `IO String' 
    In the return type of a call of `peekCString' 
    In a stmt of a 'do' block: ii <- (peekCString i) 
    In the expression: 
    do { ii <- (peekCString i); 
     ss <- peekCString s; 
     g <- newCString (isInfixOf ii ss); 
     g } 
+3

'isInfixOf'給出'Bool',而不是'''newCString'想要的'String' - 你想要做什麼? – dave4420

+0

@ dave4420謝謝!完全錯過了。如果我在s中,我試圖返回true。由於沒有CBool​​我猜定義導出將是「CString - > CString - > Bool」...? – NerdGGuy

+1

'CString - > CString - > IO Bool',在查看之後,您只需'返回$ ii'isInfixOf' ss''。 –

回答

5

現在修復

grep :: CString -> CString -> IO Bool 
grep i s = do 
    ii <- peekCString i 
    ss <- peekCString s 
    return (isInfixOf ii ss) 

foreign export ccall grep :: CString -> CString -> IO Bool 

澄清,讓我們找出錯誤消息怎麼來的是:

grep :: CString -> CString -> CString 
grep i s = do 
    ii <- peekCString i 
    ss <- peekCString s 
    g <- newCString (isInfixOf ii ss) 
    g 

grep聲明的結果類型爲CString,這是Ptr CChar型代名詞。定義的右側是一個do塊(包含多個語句),因此對於某些Monad m和某些類型a,結果類型的格式必須爲m a

聲明的結果類型Ptr CChar形式m a匹配 - 與m = Ptr, a = CChar - 所以剩下的就是找到/驗證類型構造PtrMonad實例。沒有範圍,因此

grep.hs:11:9: 
    No instance for (Monad Ptr)    -- quite 
    arising from a do statement   -- right 
    Possible fix: add an instance declaration for (Monad Ptr) -- Umm, no, not really 

第一次報告的錯誤。

第二個錯誤來自分析do-block的內容。編譯器在遇到第一個錯誤時可能會停止類型檢查,但是沒有。現在繼續進行類型檢查,假設PtrMonad。因此,在該do-block中,<-(其在desugaring成爲(>>=) :: Monad m => m a -> (a -> mb) -> m b的第一個參數之後)的每個表達式必須具有類型Ptr sometype。但是peekCString :: CString -> IO String,從而

grep.hs:11:16: 
    Couldn't match expected type `Ptr t0' with actual type `IO String' 
    In the return type of a call of `peekCString' 
    In a stmt of a 'do' block: ii <- (peekCString i) 
    In the expression: 
    do { ii <- (peekCString i); 
     ss <- peekCString s; 
     g <- newCString (isInfixOf ii ss); 
     g } 

如果編譯繼續,它將給第二peekCString線相同類型的錯誤,最後一個

Couldn't match type `Bool' with `[Char]' 
Expected type: String 
    Actual type: Bool 
In the first argument of `newCString', namely ... 

newCString的錯誤類型的參數(另加IO - Ptr不匹配)。

2

你必須使用一個一元函數,你正在做的IO的東西:

grep :: CString -> CString -> IO CString 
grep i s = do 
    ii <- peekCString i 
    ss <- peekCString s 
    newCString (isInfixOf ii ss) 

也適應您的出口條款:

foreign export ccall grep :: CString -> CString -> IO CString 
+0

謝謝!這是我想要的(除了我所做的newCString錯誤,返回IO Bool將會很好)。 ghc錯誤似乎誤導了我。 – NerdGGuy