2017-04-02 12 views
1

私はHaskellで並行性が新しく、新しいMVarがmainスレッドで作成された結果を取得しようとしています。ユーザーからの文字入力を受け取りuserThreadスレッドへの空、そしてMVARでその価値を置き、mainスレッド、それを印刷しています。ここで Haskell: "予想されるIO IO()をIO ThreadIdと一致させることができませんでした"

は私がMVARに入力された文字を入れしようとしているにこだわっている、今のところ、これまで

module Main where 

import Control.Concurrent 
import Control.Monad 
import System.IO 
import System.Random 
import Text.Printf 

data Msg = C Char | Time 


main :: IO() 
main = do 
    hSetBuffering stdout NoBuffering 
    hSetBuffering stdin NoBuffering 
    hSetEcho stdin False 

    -- shared resources 
    chan <- newEmptyMVar 
    forkIO $ userThread chan 
    --r <- takeMVar chan 
    --show(r) 


userThread :: MVar Msg -> IO() 
userThread chan = forever $ do 
    x <- getChar 
    putMVar chan (C x) 

持っているものですが、私は以下のエラーを貼り付けました

assignment1.hs:20:3: error: 
    * Couldn't match type `ThreadId' with `()' 
     Expected type: IO() 
     Actual type: IO ThreadId 
    * In a stmt of a 'do' block: forkIO $ userThread chan 
     In the expression: 
     do { hSetBuffering stdout NoBuffering; 
      hSetBuffering stdin NoBuffering; 
      hSetEcho stdin False; 
      chan <- newEmptyMVar; 
      .... } 
     In an equation for `main': 
      main 
      = do { hSetBuffering stdout NoBuffering; 
        hSetBuffering stdin NoBuffering; 
        hSetEcho stdin False; 
        .... } 
Failed, modules loaded: none. 

正しい方向へのポインタは大きな助けになるでしょう! おかげでみんな

答えて

2

forkIO $ userThread chanThreadIdを返すIOアクションがあり、かつmaindoブロックの最後の文であることは、それはそれとしてもmainリターンします。しかし、main :: IO()と宣言したので、型の不一致があります。

は、単にダミータプルを返します。

main = do 
    ... 
    forkIO $ userThread chan 
    return() 

(あり、このためvoidライブラリ関数もありますが、あなたはそれを無視することができます。)

+1

おかげで、これは助けました。私はそれだけでユーザが押した文字を印刷するために得ることができるか、今 ''(ショー)を導出使用して、私の文字をコンパイルして印刷するプログラムが、しかし、このための出力は、たとえば、 'C「g''で取得することができます? –

+1

@SebMarshあなたはあなた自身の 'Show'インスタンスを定義することができます。あるいは好きなようにメッセージを印字する関数' Msg - > String'または 'Msg - > Text'を定義することができます(' putStrLn'を呼び出してstdout ) – jberryman

+0

もう一度ありがとう。私がjberrymanに返答したとき、私はCharの場合、Stringのように動作するように私のMsgデータを得るために、このようなものを使うことができると考えました。私はこれをどうやって始めますか?私は自分のインスタンスを使用していないので、私はやや失われています。 –

2

あなたはHaskellのを学ぶよう何度もこのエラーを取得するつもりだので、私はそれを解凍したいですあなたのために:

assignment1.hs:20:3: error: 
GHCはあなたのファイル、行番号と列番号与えている

file:line:col

* Couldn't match type `ThreadId' with `()' 
     Expected type: IO() 
     Actual type: IO ThreadId 

Expected typeコンテキストに基づいて、GHCは、発現のために期待されているタイプを指し、例えば指定した型シグネチャ、またはその式から返された値を使用する方法を示します。 Actual typeは実際の式の型です。リテラル'c'

など、 map fst [('c', undefined)]は実際の型 [Char]を持って、 Charを入力
* In a stmt of a 'do' block: forkIO $ userThread chan 

を持っている。この^問題文です。 forkIOThreadId(型シグネチャから確認できます)を返します。ここでのトリッキーな部分は、その後、私が思う、型チェッカーが原因であなたの型シグネチャの種類IO()(と、あなたのdoブロックの最後の文で返された値の型がカイとして、返されるという事実を期待していた理由を知ることです言及)。あなたが開発しているよう

それはあなたがこれらのような質問に答えるために、オープンghciを持っていると便利です:

Prelude> import Control.Concurrent 
Prelude Control.Concurrent> :t forkIO 
forkIO :: IO() -> IO ThreadId 
Prelude Control.Concurrent> :t() 
() ::() 
Prelude Control.Concurrent> :t repeat() 
repeat() :: [()] 

残りはあなたが目の前にファイルを持っている場合、あなたはおそらく必要はありませんより多くのコンテキストをありますあなた:

 In the expression: 
     do { hSetBuffering stdout NoBuffering; 
      hSetBuffering stdin NoBuffering; 
      hSetEcho stdin False; 
      chan <- newEmptyMVar; 
      .... } 
     In an equation for `main': 
      main 
      = do { hSetBuffering stdout NoBuffering; 
        hSetBuffering stdin NoBuffering; 
        hSetEcho stdin False; 
        .... } 
Failed, modules loaded: none. 
+1

ありがとう、これは少し私の問題を理解するのに役立ちましたが、今私はどのように文字列のように動作する私のメッセージの種類を作るために全く新しい問題に直面している。型付きcharがリストにない場合は、既存のリストに入れたいですが、このリストにcharがすでに存在する場合は、このリストには追加されず、そのcharのすべてのインスタンスがリストから削除されます。もう少し研究を重ねるとすぐに別の質問を作成します。 –

関連する問題