2016-03-07 47 views
2

我嘗試創建一個顯示一個按鈕被點擊時文本的程序,使用哈斯克爾& Qt的,在Ubuntu用崇高的文本3 但顯然有定義信號鍵時(識別點擊按鈕時調用的信號的鍵)會出現問題。 此外,很難找到有關HsQML的文檔,這是一個加入haskell的綁定文件。的Qt:點擊按鈕=>消息應該出現在一個Haskell程序

代碼:

module Main where 

import Graphics.QML 
import Control.Concurrent 
import Control.Exception 
import Data.IORef 
import Data.Text (Text) 
import qualified Data.Text as T 

    main :: IO() 
    main = do 
     state <- newIORef $ T.pack "" 
     skey <- newSignalKey 
     clazz <- newClass [ 
      defPropertySigRO' "my_label" skey (\_ -> readIORef state), 
      defMethod' "sayHello" (\obj txt -> do 
       writeIORef state txt 
       fireSignal skey obj 
       return())] 
     ctx <- newObject clazz() 
     runEngineLoop defaultEngineConfig { 
      initialDocument = fileDocument "exemple2.qml", 
      contextObject = Just $ anyObjRef ctx} 

錯誤消息:

Build FAILED 

/home/lowley/Documents/haskell/Qt/exemple-2.hs: line 13, column 10: 
    No instance for (SignalSuffix (IO a0)) 
    arising from a use of `newSignalKey' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there is a potential instance available: 
    instance SignalSuffix (IO()) -- Defined in `Graphics.QML.Objects' 
    Possible fix: 
    add an instance declaration for (SignalSuffix (IO a0)) 
    In a stmt of a 'do' block: skey <- newSignalKey 
    In the expression: 
    do { state <- newIORef $ T.pack ""; 
     skey <- newSignalKey; 
     clazz <- newClass 
        [defPropertySigRO' "my_label" skey (\ _ -> readIORef state), 
        defMethod' "sayHello" (\ obj txt -> ...)]; 
     ctx <- newObject clazz(); 
     .... } 
    In an equation for `main': 
     main 
     = do { state <- newIORef $ T.pack ""; 
       skey <- newSignalKey; 
       clazz <- newClass 
          [defPropertySigRO' "my_label" skey (\ _ -> ...), ....]; 
       .... } 

解決了! 但我不知道爲什麼這個程序可以在不出現上述錯誤編譯:

module Main where 

import Graphics.QML 
import Control.Concurrent 
import Control.Exception 
import Data.IORef 
import qualified Data.Text as T 

main :: IO() 
main = do 
    state <- newIORef $ T.pack "" 
    skey <- newSignalKey 
    clazz <- newClass [ 
     defPropertySigRO' "result" skey (\_ -> 
      readIORef state), 
     defMethod' "factorial" (\obj txt -> do 
      let n = read $ T.unpack txt :: Integer 
      writeIORef state $ T.pack "Working..." 
      fireSignal skey obj 
      forkIO $ do 
       let out = T.take 1000 . T.pack . show $ product [1..n] 
       evaluate out 
       writeIORef state out 
       fireSignal skey obj 
      return())] 
    ctx <- newObject clazz() 
    runEngineLoop defaultEngineConfig { 
     initialDocument = fileDocument "factorial2.qml", 
     contextObject = Just $ anyObjRef ctx} 
+0

不是我主張使用它,它不是你的問題的答案,但也有一個用於haskell的qt包。 –

回答

2

有錯誤告訴你,GHC不知道什麼類型的newSignalKey創建應該有(newSignalKey :: SignalSuffix p => IO (SignalKey p)信號GHC不知道什麼p應該是,因爲你沒有指定它)。添加像這樣的明確類型簽名:

skey <- newSignalKey :: IO (SignalKey (IO())) 

應該修復您所看到的錯誤。

好的,那麼現在爲什麼它在第二個例子中工作?要了解這一點,我們必須看看GHC知道什麼以及它可以確定哪些類型的skey

在第一示例和第二示例中,skey的使用如下:

do 
    ... 
    fireSignal skey obj 
    ... 

由於fireSignal :: SignalKey p -> ObjRef() -> p(簡化的類型,用全類型的fireSignal是更一般的),GHC知道p必須IO something ,因爲它用於期望IO something動作的上下文中(作爲IO中的do塊的一部分)。它不知道something是什麼,因爲從未使用該動作的返回值。所以它留下skey :: SignalKey (IO something),並正確地報告something不明確的錯誤(它不知道什麼類型something應該是)。

在第二示例中,SKEY然而,也用於以下模式:

forkIO $ do 
    ... 
    fireSignal skey obj 

由於forkIO期望一個IO動作返回()類型的值,GHC現在知道fireSignal skey obj :: IO()(因此在這種情況下它知道something必須是())。這意味着p不再含糊不清,它必須是IO()

+0

謝謝,它的作品!但請看看我的編輯。 – lolveley

+0

不錯!給我一秒,我會編輯答案,以更深入地解釋類型檢查過程在這種情況下 – bennofs

+0

增加解釋爲什麼第二個示例工作 – bennofs

相關問題