并发Haskell:对自定义数据类型中的数据执行操作

时间:2017-04-02 18:03:41

标签: haskell concurrency

到目前为止,在这个程序中我有一个自定义数据类型Msg,它是C Char。在程序中,创建一个单独的线程,一个单独的函数userThread侦听键击,并存储在MVar中发送的char,它充当main和{{之间的简单通信通道。 1}}

我已经到了这一点,使用userThread我可以将Msg打印到终端,就像一个字符串。如果用户键入deriving (Show),则输出为:

j

(注意当我只想要字符本身时它也会打印出来)

我有一个现有的列表,我的目标是如果char不在该列表中,然后添加它。如果是,则不要添加它并删除列表中该char的所有实例。

例如,如果用户键入C 'j' ,则

c

[a,b] becomes [a,b,c]

我目前的代码如下:

[f,c,c,h,c] becomes [f,h]

我很困惑,因为我能够在我的module Main where import Control.Concurrent import Control.Monad import System.IO import System.Random import Text.Printf data Msg = C Char deriving (Show) main :: IO () main = loop where loop = do hSetBuffering stdout NoBuffering hSetBuffering stdin NoBuffering hSetEcho stdin False --already existing list let x = [1, 's', 'g', 4 ,5] chan <- newEmptyMVar forkIO $ userThread (chan) r <- takeMVar (chan) putStrLn $ show x print r -- Listens for keystrokes from the user, the passes them to the main thread userThread :: MVar Msg -> IO () userThread chan = do c <- getChar putMVar chan (C c) 上执行Print这样的操作,因为它的实际内容是一个字符。但是当我尝试使用Msg将其添加到列表时,编译错误会显示:

r:x

如何让我的Msg适合这个列表?非常感谢你的帮助。

1 个答案:

答案 0 :(得分:0)

问题是您的列表不包含C Char,而是Char。这可以通过let x = [C '1',C 's',C 'g',C '4',C '5']来解决。

您的userThreadC Char放入chan,因此当您使用takeMVar (chan)解压缩并将其绑定到rr时类型为Msg。因为在Haskell列表中只能保存相同类型的值,所以不能将Msg添加到[Char],因此会出现错误。制作xMsg的所有元素,一切都会好(希望......)。或者,您可以实现

toChar :: Msg -> Char toChar C c = c

如果您坚持在列表中添加(toChar r):x,请执行Char之类的操作。

来自x的remvoing元素,请参阅this。然后你可以写一些类似的东西:

if elem r x then newX = remove r x else newX = r:x --if x contains Msg
if elem cr x then newX = remove cr x else newX = cr:x
   where cr = toChar r --if you insist on having chars in x...
希望有所帮助。