gpt4 book ai didi

haskell - 如何在 Haskeline 中在运行时更改 Tab 完成的内容?

转载 作者:行者123 更新时间:2023-12-03 16:19:18 24 4
gpt4 key购买 nike

我想写一个文本界面,提供一些默认的命令。该程序支持这些命令的制表符补全。
该程序还记录用户输入并将其存储在 StateData 中。 .现在我希望这个程序支持这些用户输入的选项卡完成。例如:

*Main > main
> read a<tab> -- press tab and no suggestions (read is a default command)
> read abcde
...
> read a<tab> -- press tab
abcde -- suggestions
是否可以在不使用像 IORef 这样的不安全机制的情况下做到这一点? ?有没有办法通过更新 st来自 loop (在 repl 中)到 replSettings startState (在 repl 中)?
我是 Haskeline 的新手,感谢您的时间。
repl :: StateData -> IO()
repl startState = runInputT (replSettings startState) $ loop startState
where
loop :: StateData -> InputT IO ()
loop st = do
inputL <- getInputLine "> "
case inputL of
Nothing -> return ()
Just "quit" -> outputStrLn "--Exited--" >> return ()
Just ipt -> do (opt, st') <- process ipt `runStateT` st
...
loop st'

replSettings :: StateData -> Settings IO
replSettings st =
Settings
{ complete = replCompletion st,
historyFile = Just "history.txt",
autoAddHistory = True
}

replCompletion :: StateData -> CompletionFunc IO
replCompletion st = completeWordWithPrev Nothing [' '] st (\x y -> return $ completionGenerator x y)

completionGenerator :: String -> String -> StateData -> [Completion]
completionGenerator "" c st =
commandSuggestion c (updatesSuggestions st) -- I wish to update it at run time
completionGenerator p c st = ...

最佳答案

IORef不是不安全的;您已经在 IO ,所以这是在此处添加可变状态的一种完全合理的方式。
但如果你想避免 IO ,您可以简单地使用 StateT StateData IO作为 InputT 的底层 monad ,以及 Settings 中的完成函数.看来您已经在尝试使用 StateT反正。这是一个完整的示例,它只是将每个条目添加到列表中并天真地自动完成它们:

import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.State (StateT, evalStateT, get, modify)
import Data.List (isPrefixOf)
import System.Console.Haskeline

type StateData = [String]

main :: IO ()
main = repl []

repl :: StateData -> IO ()
repl startState
= flip evalStateT startState
$ runInputT replSettings loop
where
loop :: InputT (StateT StateData IO) ()
loop = do
inputL <- getInputLine "> "
case inputL of
Nothing -> pure ()
Just "quit" -> outputStrLn "--Exited--"
Just ipt -> do
-- Just add each entry to the state directly.
lift $ modify (ipt :)
loop

replSettings :: Settings (StateT StateData IO)
replSettings = Settings
{ complete = replCompletion
, historyFile = Just "history.txt"
, autoAddHistory = True
}

replCompletion :: CompletionFunc (StateT StateData IO)
replCompletion = completeWordWithPrev Nothing " " completionGenerator

completionGenerator :: String -> String -> StateT StateData IO [Completion]
completionGenerator prefix suffix = do
st <- get
-- Trivial completion that just ignores the suffix.
pure $ fmap (\ s -> Completion s s True)
$ filter (prefix `isPrefixOf`) st
完成生成器也可以使用 MonadState 编写(来自 mtl )使其无法访问 IO ,而其他代码同样可以使用这种纯状态,同时对 IO 不可知。 .但除此之外,因为您已经在 IO在此代码中, StateT StateData IO/ get/ modifyReaderT (IORef StateData) IO 没有区别/ readIORef/ modifyIORef .
事实上,如果你输入 IORefStateData ,假设它是您代码中更复杂的记录类型,后者是使其某些部分可变而其他部分不可变的好方法。
data StateData = StateData
{ mutableThing :: !(IORef Thing)
, immutableStuff :: !Stuff

}

关于haskell - 如何在 Haskeline 中在运行时更改 Tab 完成的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66859656/

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