1

我是haskell 的新手,我正在尝试编写我的第一个haskell C 库。这是我第一次使用 Foreign.C 模块。我在示例中迷失了方向并且陷入了困境。到目前为止,这是我想出的:

{-# 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 }
4

2 回答 2

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

声明的结果类型grepCString,它是 的类型同义词Ptr CChar。定义的右侧是一个 do-block(包含多个语句),因此结果类型必须具有m asomeMonad m和 some type的形式a

声明的结果类型与Ptr CChar表单匹配,因此剩下的就是查找/验证类型构造函数的实例。范围内没有,因此m am = Ptr, a = CCharMonadPtr

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 的内容。编译器本可以在遇到第一个错误时停止类型检查,但没有。现在进一步的类型检查在假设Ptr是 a的情况下继续进行Monad。所以在那个 do 块中, a 右边的每个表达式<-(在脱糖后成为 a 的第一个参数(>>=) :: Monad m => m a -> (a -> mb) -> m b)必须具有 type 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不匹配)的错误类型的参数。

于 2012-11-09T13:55:20.950 回答
2

在执行 IO 操作时,您必须使用 monadic 函数:

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
于 2012-11-09T10:15:57.417 回答