2017-04-02 5 views
1

Ich bin neu zu Nebenläufigkeit in Haskell und ich versuche, ein Ergebnis zu erhalten, wo eine neue MVar im Thread main gemacht wird, wird übergeben leer zum userThread Thread, der eine Zeicheneingabe vom Benutzer nimmt, dann legt diesen Wert in eine MVar und hat den main Thread es drucken.Haskell: "Ich konnte den erwarteten Typ IO() mit IO ThreadId nicht"

Hier ist, was ich

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) 

Gerade jetzt so weit, ich zu versuchen, die eingegebenen Zeichen in die MVar bin stecken zu setzen, habe ich den Fehler unter

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. 

geklebt Irgendwelche Hinweise in die richtige Richtung wären eine große Hilfe! Vielen Dank alle

Antwort

2

forkIO $ userThread chan ist eine IO-Aktion, die ThreadId zurückkehrt, und wobei die letzte Anweisung im maindo Block, macht es main zurück, die als gut. Sie haben jedoch main :: IO() deklariert, so dass ein Typ nicht übereinstimmt.

Einfach ein Dummy-Tupel zurückgeben.

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

(Es gibt auch eine void Bibliotheksfunktion für diese, aber Sie können es ignorieren.)

+1

Danke, das hat geholfen. Ich kann jetzt das Programm zum kompilieren und Drucken meines Chars mit 'Ableiten (Zeigen)', aber die Ausgabe dafür ist zum Beispiel 'C 'g'', wie kann ich es bekommen, nur das Zeichen vom Benutzer gedrückt zu drucken ? –

+1

@SebMarsh können Sie Ihre eigene 'Show' -Instanz definieren oder Sie können eine Funktion' Msg -> String' oder 'Msg -> Text' definieren, die eine Nachricht ganz nach Ihren Wünschen ausgibt (rufen Sie dann' putStrLn' auf, um sie in stdout zu schreiben)) – jberryman

+0

Danke nochmal. Als ich auf jberryman antwortete, dachte ich mir, dass ich so etwas verwenden könnte, um meine Msg-Daten als String zu verwenden, wenn es ein Char ist. Wie würde ich damit anfangen? Ich habe meine eigenen Instanzen vorher nicht benutzt, also bin ich etwas verloren. –

2

Da dieser Fehler über bekommen sind und über wie Sie Haskell lernen, wollte ich es auspacken für Sie:

assignment1.hs:20:3: error: 

GHC Sie die Datei, die Zeilennummer und Spaltennummer geben: file:line:col

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

Expected type bezieht sich auf den Typ, den GHC für einen Ausdruck erwartet, basierend auf dem Kontext, z. eine Typ-Signatur, die Sie angegeben haben, oder die Art, wie Sie einen Wert verwenden, der von diesem Ausdruck zurückgegeben wird. Actual type ist der tatsächliche Typ des Ausdrucks, z. eine wörtliche 'c' hat Char geben, hat map fst [('c', undefined)] tatsächliche Typ [Char] usw.

* In a stmt of a 'do' block: forkIO $ userThread chan 

Diese^ist die Problemstellung. forkIO gibt eine ThreadId (die Sie von seiner Typ-Signatur sehen können) zurück. Der heikle Teil hier, dann nehme ich an, ist zu wissen, warum der Typchecker einen Typ IO() erwartet hat (wegen Ihrer Typsignatur und der Tatsache, dass der in der letzten Anweisung Ihres do Block zurückgegebene Wert der zurückgegebene Typ ist, wie Chi Erwähnungen).

Es ist nützlich zu haben ghci offen Sie Fragen wie diese beantworten zu helfen, wie Sie entwickeln:

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

Der Rest ist mehr Kontext, die Sie wahrscheinlich, wenn Sie die Datei vor haben nicht brauchen Sie:

 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

Danke, das hat mir geholfen, mein Problem ein wenig zu verstehen, aber jetzt stehe ich vor einem völlig neuen Problem, wie ich meinen Msg-Typ wie einen String verhalten kann. Ich möchte es in eine bestehende Liste einfügen, wenn das eingegebene Zeichen nicht in der Liste ist. ABER wenn das Zeichen bereits in dieser Liste existiert, wird es nicht hinzugefügt und alle Instanzen dieses Zeichens werden aus der Liste entfernt. Ich werde kurz nach ein wenig mehr Recherche eine weitere Frage stellen. –

Verwandte Themen