Qt:按钮点击=>一个消息应该出现在haskell程序中 [英] Qt : button click => a message should appear in a haskell program

查看:137
本文介绍了Qt:按钮点击=>一个消息应该出现在haskell程序中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试创建一个程序,该程序在单击按钮时显示文本,使用haskell& Qt,在Ubuntu上使用崇高的文字3.
但是,显然在定义信号键时(识别按钮被点击时调用的信号的键)会出现问题。
此外,很难找到关于HsQML的文档,绑定加入haskell& Qt。

code:

 模块Main其中

import Graphics.QML
导入Control.Concurrent
导入Control.Exception
导入Data.IORef
导入Data.Text(文本)
导入限定数据.Text as T

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

错误信息:

 建立失败

/ h ome / lowley / Documents / haskell / Qt / exemple-2.hs:第13行,第10列:
由于使用`newSignalKey'$ b而没有(SignalSuffix(IO a0))
的实例$ b类型变量`a0'不明确
可能的修正:添加修复这些类型变量的类型签名
注意:有一个潜在的实例可用:
instance SignalSuffix(IO ()) - 在`Graphics.QML.Objects'中定义
可能的修正:
添加一个实例声明(SignalSuffix(IO a0))
在'do'块:skey< - newSignalKey
在表达式中:
do {state< - newIORef $ T.pack;
skey< - newSignalKey;
clazz < - newClass
[defPropertySigRO''my_label'skey(\ _ - > readIORef状态),
defMethod'sayHello(\ obj txt - > .. 。)];
ctx< - newObject clazz();
....}
在`main'等式中:
main
= do {state< - newIORef $ T.pack;
skey< - newSignalKey;
clazz < - newClass
[defPropertySigRO'my_labelskey(\ _ - > ...),....];
....}

已解决!
但我想知道为什么这个程序可以在没有上述错误的情况下编译:

  module Main其中

导入Graphics.QML
导入Control.Concurrent
导入Control.Exception
导入Data.IORef
将限定的Data.Text导入为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.packWorking ...
fireSignal skey obj
forkIO $ do
let out = T.take 1000。T.显示$ product [1..n]
评估出
writeIORef状态输出
fireSignal skey obj
return())]
ctx < - ne wObject clazz()
runEngineLoop defaultEngineConfig {
initialDocument = fileDocumentfactorial2.qml,
contextObject = Just $ anyObjRef ctx}

解决方案

有错误告诉您GHC不知道 newSignalKey 应该有( newSignalKey :: SignalSuffix p => IO(SignalKey p)。 GHC不知道 p 应该是什么,因为你没有指定它)。添加一个像这样的显式类型签名:

$ p $ s code 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块)。但它不知道是什么,因为 IO 动作的返回值从不使用。所以它留下了 skey :: SignalKey(IO something),并正确地报告错误 something 是不明确的(它不知道什么类型应该是)。



在第二个例子中,skey也被使用在以下模式中:

  forkIO $ do 
...
fireSignal skey obj

由于 forkIO 期望 IO 返回()类型值的动作,GHC现在知道 fireSignal skey obj :: IO()(所以在这种情况下,它知道 something 必须是())。这意味着 p 不再含糊不清,它必须是 IO()


I try to create a program which displays a text when a button is clicked, using haskell & Qt, on ubuntu using sublime text 3. But apparently there is a problem when defining the signal key (the key which will identify the signal called when the button is clicked). Moreover, it's hard to find a documentation about HsQML, the binding joining haskell & Qt.

code:

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}

error message:

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 (\ _ -> ...), ....];
               .... }

SOLVED! but I wonder why this program can be compiled without the above error:

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}

解决方案

There error tells you that GHC doesn't know what type the signal created by newSignalKey should have (newSignalKey :: SignalSuffix p => IO (SignalKey p). GHC does not know what p should be, since you don't specify it). Adding an explicit type signature like this:

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

should fix the error that you are seeing.

Ok, so now why does it work in the second example? To understand that, we have to look at what GHC knows and what it can determine about the type of skey.

In the first example and in the second example, skey is used as follows:

do
  ...
  fireSignal skey obj
  ...

Because fireSignal :: SignalKey p -> ObjRef () -> p (simplified type, the full type of fireSignal is more general), GHC knows that p must be IO something, because it is used in a context where an IO something action is expected (as part of a do block in IO). It does not know what something is though, since the return value of that IO action is never used. So it is left with skey :: SignalKey (IO something), and rightly reports an error that something is ambiguous (it doesn't know what type something should be).

In the second example, skey is however also used in the following pattern:

forkIO $ do
  ...
  fireSignal skey obj

Since forkIO expects an IO action that returns a value of type (), GHC now knows that fireSignal skey obj :: IO () (so in this case, it knows that something must be ()). That means that p is no longer ambiguous, it must be IO ().

这篇关于Qt:按钮点击=&gt;一个消息应该出现在haskell程序中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆