I’m new to haskell and I’m attempting to write my first haskell C library. This is my first time using the Foreign.C module. I’m getting lost in examples and have become stuck. This is what I have come up with so far:
{-# 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
I get the following error:
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 }
Now that the fix
is clarified, let us find out how the error messages come to be:
The declared result type of
grepisCString, which is a type synonym forPtr CChar. The right hand side of the definition is a do-block (with more than one statement), so the result type must have the formm afor someMonad mand some typea.The declared result type
Ptr CCharmatches the formm a– withm = Ptr, a = CChar– and so what remains is to find/verify theMonadinstance of the type constructorPtr. There is none in scope, hencethe first reported error.
The second error comes from analysing the contents of the do-block. The compiler could have stopped type-checking upon encountering the first error, but didn’t. Now the further type checking continues under the assumption that
Ptrwere aMonad. So in that do-block, every expression on the right of a<-(which, after desugaring becomes the first argument of a(>>=) :: Monad m => m a -> (a -> mb) -> m b), must have typePtr sometype. ButpeekCString :: CString -> IO String, thusIf the compiler continued, it would give the same type error for the second
peekCStringline, and finally afor the wrongly typed argument of
newCString(plus anotherIO–Ptrmismatch).