2

How does history management work in GHCI or other Haskell-based REPLs? Since Haskell is a pure language, I guess it's implemented using a monad, perhaps the state monad.

Kindly note I'm a beginner in Haskell, so please provide a detailed explanation rather than just linking to the source.

dimid
  • 7,285
  • 1
  • 46
  • 85
  • 2
    GHCi history is not implemented in Haskell at all, it is a part of a third-party library called `readline` which is written in C. – n. m. could be an AI Jun 19 '16 at 15:41
  • 1
    This page on the Haskell Wiki [(link)](https://wiki.haskell.org/Simple_StateT_use) contains code for a number guessing game written using the StateT monad transformer. If you understand how that code works I'll supply an answer to your question. If you do not understand how that program works I suggest you read up on monads and monad transformers. Here are some monad transformers links: [(link)](https://en.wikibooks.org/wiki/Haskell/Monad_transformers) [(link)](https://github.com/kqr/gists/blob/master/articles/gentle-introduction-monad-transformers.md) – ErikR Jun 19 '16 at 15:45
  • Thanks, feel free to answer, and I'll read it after reading the transformers links – dimid Jun 19 '16 at 15:56
  • 1
    Note that it could indeed be implemented in terms of a variant of `State` (or more precisely `StateT History IO`, where `History = [String]` or something). It could even be implemented inside `IO` alone: basically `IO` lets one do imperative programming with side effects and mutable variables (`IORef History`). It happens that GHCi reused a C library for that, rather than reinventing the wheel. – chi Jun 19 '16 at 16:23

1 Answers1

2

This is a simplified example of how a program might keep a history of commands entered by the user. It basically has the same structure as the number guessing game, so once you understand that you should have no trouble understanding this:

import Control.Monad.State
import Control.Monad

shell :: StateT [String] IO ()
shell = forever $ do
  lift $ putStr "$ "
  cmd <- lift getLine
  if cmd == "history"
    then do hist <- get
            lift $ forM_ hist $ putStrLn
    else modify (++ [cmd])

main = do putStrLn "Welcome to the history shell."
          putStrLn "Type 'history' to see your command history."
          execStateT shell []
ErikR
  • 51,541
  • 9
  • 73
  • 124
  • Thanks a lot, but I'm having trouble to combine it with my code. Could you take a look? http://stackoverflow.com/questions/37930204/combining-statet-with-inputt – dimid Jun 20 '16 at 19:20