haskelliogtk2hs

gtk2hs: Couldn't match expected type ‘IO [Int]’ with actual type ‘[Int]’


everyone I want to get a list of numbers from GUI to do some changes by using gtk2hs, and return the result to GUI. However, it got lots of error. I'm a rookie of Haskell, could someone tell me how to fix it. Thanks!!

import Graphics.UI.Gtk
import Data.List 

main :: IO ()
main= do
  initGUI
  window <- windowNew
  set window [windowTitle := "Text Entry", containerBorderWidth := 10]

  vb <- vBoxNew False 0
  containerAdd window vb

  hb <- hBoxNew False 0
  boxPackStart vb hb PackNatural 0

  txtfield <- entryNew
  boxPackStart hb txtfield PackNatural 5
  button <- buttonNewFromStock stockInfo
  boxPackStart hb button PackNatural 0

  txtstack <- statusbarNew
  boxPackStart vb txtstack PackNatural 0
  id <- statusbarGetContextId txtstack "Line"

  widgetShowAll window
  widgetSetSensitivity button False

  onEntryActivate txtfield (saveText txtfield button txtstack id)
  onPressed button (statusbarPop txtstack id)
  onDestroy window mainQuit
  mainGUI

  saveText :: Entry -> Button -> Statusbar -> ContextId -> IO ()
  saveText fld b stk id = do
                        txt <- entryGetText fld
                        result <- convert txt
                        lt <- first resultt
                        result2 <- combineTogether lt
                        mesg <-  " is the first element of input text" ++ txt

                        widgetSetSensitivity b True
                        msgid <- statusbarPush stk id mesg
                        return ()
convert :: [Int] -> IO [Int]
convert lstr = map read $ words lstr :: [Int]

converttoStr lst = map show lst 

combineTogether :: [Int] -> IO[Char]
combineTogether lst = intercalate " " (converttoStr lst)

first :: [Int] -> IO [Int]
first (x:xs) = xs

Here are the error message:

[1 of 1] Compiling Main             ( testproject.hs, testproject.o )

testproject.hs:39:38:
Couldn't match type ‘[]’ with ‘IO’
Expected type: IO Char
  Actual type: [Char]
In a stmt of a 'do' block:
  mesg <- " is the first element of input text" ++ txt
In the expression:
  do { txt <- entryGetText fld;
       result <- convert txt;
       lt <- first result;
       result2 <- combineTogether lt;
       .... }
In an equation for ‘saveText’:
    saveText fld b stk id
      = do { txt <- entryGetText fld;
             result <- convert txt;
             lt <- first result;
             .... }

testproject.hs:39:79:
Couldn't match type ‘Int’ with ‘Char’
Expected type: [Char]
  Actual type: [Int]
In the second argument of ‘(++)’, namely ‘txt’
In a stmt of a 'do' block:
  mesg <- " is the first element of input text" ++ txt

testproject.hs:48:16:
Couldn't match expected type ‘IO [Int]’ with actual type ‘[Int]’
In the expression: map read $ words lstr :: [Int]
In an equation for ‘convert’:
    convert lstr = map read $ words lstr :: [Int]

testproject.hs:48:33:
Couldn't match type ‘Int’ with ‘Char’
Expected type: String
  Actual type: [Int]
In the first argument of ‘words’, namely ‘lstr’
In the second argument of ‘($)’, namely ‘words lstr’

testproject.hs:51:23:
Couldn't match expected type ‘IO [Char]’ with actual type ‘[Char]’
In the expression: intercalate " " (converttoStr lst)
In an equation for ‘combineTogether’:
    combineTogether lst = intercalate " " (converttoStr lst)

testproject.hs:54:16:
Couldn't match expected type ‘IO [Int]’ with actual type ‘[Int]’
In the expression: xs
In an equation for ‘first’: first (x : xs) = xs

Solution

  • Do-notation is syntactic sugar for a series of bind operations. With that in mind, it makes sense that every line in your do-block needs to be of type 'IO' because that is how you defined your function.

    Try changing the following line

    mesg <- " is the first element of input text" ++ txt
    

    to

    let mesg = " is the first element of input text" ++ txt
    

    (which is also equivalent to)

    mesg <- return " is the first element of input text" ++ txt
    

    That should fix the issue you have on that particular line. And it makes even more sense if we look at the type signature of the 'return' function:

    Monad m => a -> m a
    

    This says, "supply an 'a', and I will give you an 'a' wrapped inside a monad" (in this case the IO monad)

    I hope this helps a bit.