gpt4 book ai didi

Haskell - 尝试使用 Prelude.read 使输出类型 a 也适用于 String

转载 作者:行者123 更新时间:2023-12-04 10:07:03 24 4
gpt4 key购买 nike

我正在制作一个我永远不会放在 github 上或分发的小程序,我注意到一种在命令行上询问内容并获得答案并使用它的模式。所以我想把这个模式变成一个函数。

askQuestion :: (Read a) => String -> IO a
askQuestion q = do
putStrLn q
read <$> getLine

当然,这种函数并不是特别安全,因为当无法解析用户给出的答案时,它会抛出错误。这就是为什么推荐 readMaybe 或 readEither 的原因。但是因为我是代码的唯一用户,所以我不介意,因为我知道我的程序需要什么。

在此之后,我想到了我的代码经常使用的另一种模式,它要求用户在两个选项之间进行选择,然后我的程序根据答案进行分支。我也为此做了一个功能。
askOption :: String -> String -> String -> IO a -> IO a -> IO a
askOption q a1 a2 ac1 ac2 = do
putStrLn q
ans <- getLine
if a1 == ans
then ac1
else if a2 == ans
then ac2
else error $ "Not one of the options for question " ++ q

这段代码完美地满足了我的需求,并使我的主要功能看起来很干净。但是当我注意到
putStrLn q
ans <- getLine

在我的 askOption 函数中,我想用 askQuestion 函数替换那个块。

这就是我的问题所在,显然 read 无法将字符串解析为字符串。现在我想很明显你不能期望,但我希望 read 只是转发字符串而不对其做任何事情。

我想知道的是,是否有可能有一个系统,如果 read 注意到它是一个字符串,它只是通过它。我想保持干净的类型 IO a 并且不必重构我的代码以使用 IO Maybe a 或 IO Each String a。我知道我可以处理错误,然后在句柄中使用 getLine 来获得答案。但这需要我每次输入两次答案。一次失败,一次成功。
ans <- handle (\(SomeException e) -> putStrLn "Answer again" >> getLine) $ askQuestion "Give Input"  

这将保留我想要的类型,但对实际程序来说是一种痛苦。

我想到的另一个选项是检查 ans 是否是 askQuestion 函数中的字符串,以及它是否返回字符串并执行读取。但这会破坏 IO a 类型,因为 IO String 不等于 IO a。

总结:有没有办法让 askQuestion 的类型签名在传递无法作为字符串读回的答案时保持 IO 状态。我知道在实际实践中使用 readEither/readMaybe 是首选,但我只是想这样做是为了好玩。

最佳答案

您不能使用现有的 askQuestion 来执行此操作函数,因为它使用了 read已硬连线,而您不想使用 read在这种情况下。为了使这个函数更灵活,从中提取一个参数:

askQuestion' :: (String -> a) -> String -> IO a
askQuestion' parse prompt = do
putStrLn prompt
parse <$> getLine

那么你原来的 askQuestion可以定义为:
askQuestion :: (Read a) => String -> IO a
askQuestion = askQuestion' read

和您的新 askOption可以使用更灵活的功能:
askOption :: String -> String -> String -> IO a -> IO a -> IO a
askOption q a1 a2 ac1 ac2 = do
ans <- askQuestion' id q
if a1 == ans
then ac1
else if a2 == ans
then ac2
else error $ "Not one of the options for question " ++ q

关于Haskell - 尝试使用 Prelude.read 使输出类型 a 也适用于 String,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61533451/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com