到目前为止,在这个程序中我有一个自定义数据类型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适合这个列表?非常感谢你的帮助。
答案 0 :(得分:0)
问题是您的列表不包含C Char
,而是Char
。这可以通过let x = [C '1',C 's',C 'g',C '4',C '5']
来解决。
您的userThread
将C Char
放入chan
,因此当您使用takeMVar (chan)
解压缩并将其绑定到r
,r
时类型为Msg
。因为在Haskell列表中只能保存相同类型的值,所以不能将Msg
添加到[Char]
,因此会出现错误。制作x
类Msg
的所有元素,一切都会好(希望......)。或者,您可以实现
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...
希望有所帮助。