I have a program I'm trying to create of a one line text editor
I've come to a bit of a wall at this point.
I have a list of letters called left and one called right
perhaps in a function or a do list how can I set left to left ++ char where char is a user inputted char. I understand it's not possible to modify lists but can I redefine them?
If this pseudo code helps
left = "hello"
in = get user input
left = left ++ in
Thanks in advance
This is what the State Monad is for. The link should help (it points to a tutorial). Your example would then become:
type Line = State String ()
addInput :: String -> Line
addInput inp = do
left <- get
put $ left ++ inp
runState (addInput <user input>) "hello"
This does, however, require getting to know monads a bit. Follow the examples in the link.
Related
I'm currently working on an assignment. I have a function called gamaTipo that converts the values of a tuple into a data type previously defined by my professor.
The problem is: in order for gamaTipo to work, it needs to receive some preceding element. gamaTipo is defined like this: gamaTipo :: Peca -> (Int,Int) -> Peca where Peca is the data type defined by my professor.
What I need to do is to create a funcion that takes a list of tuples and converts it into Peca data type. The part that im strugling with is taking the preceding element of the list. i.e : let's say we have a list [(1,2),(3,4)] where the first element of the list (1,2) always corresponds to Dirt Ramp (data type defined by professor). I have to create a function convert :: [(Int,Int)] -> [Peca] where in order to calculate the element (3,4) i need to first translate (1,2) into Peca, and use it as the previous element to translate (3,4)
Here's what I've tried so far:
updateTuple :: [(Int,Int)] -> [Peca]
updateTuple [] = []
updateTuple ((x,y):xs) = let previous = Dirt Ramp
in (gamaTipo previous (x,y)): updateTuple xs
Although I get no error messages with this code, the expected output isn't correct. I'm also sorry if it's not easy to understand what I'm asking, English isn't my native tongue and it's hard to express my self. Thank you in advance! :)
If I understand correctly, your program needs to have a basic structure something like this:
updateTuple :: [(Int, Int)] -> [Peca]
updateTuple = go initialValue
where
go prev (xy:xys) =
let next = getNextValue prev xy
in prev : (go next xys)
go prev [] = prev
Basically, what’s happening here is:
updateTuple is defined in terms of a helper function go. (Note that ‘helper function’ isn’t standard terminology, it’s just what I’ve decided to call it).
go has an extra argument, which is used to store the previous value.
The implementation of go can then make use of the previous value.
When go recurses, the recursive call can then pass the newly-calculated value as the new ‘previous value’.
This is a reasonably common pattern in Haskell: if a recursive function requires an extra argument, then a new function (often named go) can be defined which has that extra argument. Then the original function can be defined in terms of go.
using gogol package,
follow example got
> exampleGetValue
-- ValueRange' {_vrValues = Just [String "2018/1/1",String "2018/1/2"], _vrRange = Just "'\24037\20316\34920\&1'!A1:1", _vrMajorDimension = Just VRMDRows}
> exampleGetValue >>= return . view vrValues
-- [String "2018/1/1",String "2018/1/2"]
> mapM_ (print) (exampleGetValue >>= return . view vrValues)
String "2018/1/1"
String "2018/1/2"
Why there will be a string of words
How to do I can only show
2018/1/1
2018/1/2
Take a look at
[String "2018/1/1",String "2018/1/2"]
the result of
> exampleGetValue >>= return . view vrValues
Here the strings you are interested in, like "2018/1/1" are contained in another datatype String, which has, I assume, an automatically derived show instance, which will print the name of the Data constructor String.
You need to unpack the strings somehow to get rid of the printing of the word String.
As this is stackoverflow, and we are considered to provide answers, I will give you one possibility now, but before you read it, try to do it yourself:
unpackString (String w) = w
mapM_ (print . unpackString) (exampleGetValue >>= return . view vrValues)
You have to determine the type signature for unpackString yourself, as you didn't provided any types.
How do you get text from a textView in Haskell?
I am not sure I am doing it right. The only "get" function I could find in the TextView class is textViewGetBuffer which evaluates to an IO TextBuffer, not a string.
I am trying to get the string value of the IO TextBuffer using textBufferGetText :: self -> TextIter -> TextIter -> Bool -> String, but cannot figure out what to specify as the TextIter values.
The TextIter values specify the start and end of the range to get text, but when I looked up the TextIter datatype it did not specify any value constructors I could use.
name = textBufferGetText (textViewGetBuffer txtView) start end True
Any suggestions/help would be greatly appreciated.
(Disclaimer: I don't know how to use GTK in Haskell and I can't install it on this machine, so I can't test this)
Looking at the documentation, there are several methods to get a TextIter value from a TextBufferClass. The ones you're probably interested in are the textBufferGetStartIter and textBufferGetEndIter, which each take a TextBufferClass and return IO TextIter, so you could write a function something like
textViewGetValue :: TextViewClass self => self -> IO String
textViewGetValue tv = do
buf <- textViewGetBuffer tv
start <- textBufferGetStartIter buf
end <- textBufferGetEndIter buf
value <- textBufferGetText buf start end True
return value
which should work. Technically, the last two lines could just be textBufferGetText buf start end True, but I think this makes it a bit more clear what is happening.
EDIT: I should say that I found these methods in Graphics.UI.Gtk.Multiline.TextView, Graphics.UI.Gtk.Multiline.TextBuffer, and Graphics.UI.Gtk.Multiline.TextIter, so you may have to import those as well. But I don't know what all is already in your namespace.
I have an assignment which is to create a calculator program in Haskell. For example, users will be able to use the calculator by command lines like:
>var cola =5; //define a random variable
>cola*2+1;
(print 11)
>var pepsi = 10
>coca > pepsi;
(print false)
>def coke(x,y) = x+y; //define a random function
>coke(cola,pepsi);
(print 15)
//and actually it's more complicated than above
I have no clue how to program this in Haskell. All I can think of right now is to read the command line as a String, parse it into an array of tokens. Maybe go through the array, detect keywords such "var", "def" then call functions var, def which store variables/functions in a List or something like that. But then how do I store data so that I can use them later in my computation?
Also am I on the right track because I am actually very confused what to do next? :(
*In addition, I am not allowed to use Parsec!*
It looks like you have two distinct kinds of input: declarations (creating new variables and functions) and expressions (calculating things).
You should first define some data structures so you can work out what sort of things you are going to be dealing with. Something like:
data Command = Define Definition | Calculate Expression | Quit
type Name = String
data Definition = DefVar Name Expression | DefFunc Name [Name] Expression
-- ^ alternatively, implement variables as zero-argument functions
-- and merge these cases
data Expression = Var Name | Add Expression Expression | -- ... other stuff
type Environment = [Definition]
To start off with, just parse (tokenise and then parse the tokens, perhaps) the stuff into a Command, and then decide what to do with it.
Expressions are comparatively easy. You assume you already have all the definitions you need (an Environment) and then just look up any variables or do additions or whatever.
Definitions are a bit trickier. Once you've decided what new definition to make, you need to add it to the environment. How exactly you do this depends on how exactly you iterate through the lines, but you'll need to pass the new environment back from the interpreter to the thing which fetches the next line and runs the interpreter on it. Something like:
main :: IO ()
main = mainLoop emptyEnv
where
emptyEnv = []
mainLoop :: Environment -> IO ()
mainLoop env = do
str <- getLine
case parseCommnad str of
Nothing -> do
putStrLn "parse failed!"
mainLoop env
Just Quit -> do
return ()
Just (Define d) -> do
mainLoop (d : env)
Just (Calculate e) -> do
putStrLn (calc env e)
mainLoop env
-- the real meat:
parseCommand :: String -> Maybe Command
calc :: Environment -> Expression -> String -- or Integer or some other appropriate type
calc will need to look stuff up in the environment you create as you go along, so you'll probably also need a function for finding which Definition corresponds to a given Name (or complaining that there isn't one).
Some other decisions you should make:
What do I do when someone tries to redefine a variable?
What if I used one of those variables in the definition of a function? Do I evaluate a function definition when it is created or when it is used?
These questions may affect the design of the above program, but I'll leave it up to you to work out how.
First, you can learn a lot from this tutorial for haskell programming
You need to write your function in another doc with .hs
And you can load the file from you compiler and use all the function you create
For example
plus :: Int -> Int -- that mean the function just work with a number of type int and return Int
plus x y = x + y -- they receive x and y and do the operation
I'm trying to write a function in Haskell which checks for some things and then recurses based on some minimal user input. In order to do that I think I have to use do blocks.
cip :: [Argument] -> [Argument] -> Bool -> Bool -> IO()
cip (a:args) pargs burden gameover = do
let nasko = a:pargs
putStrLn (getPremise a)
let newgraph = Carneades.mkArgGraph nasko
let newcaes = (CAES (newgraph,audience2,assStandarts))
let answer = (acceptable (mkProp (getPremise a)) newcaes )
print answer
if(answer==True)
then (cip args nasko burden gameover)
else do
print "One of the arguments is not proved. Here are the premises that need proving"
print (propsForFixing newcaes a)
print "Let's see what you have for the first Propositon"
--add an if to check if no applicable arguments.
print (argumentScanHelp (head (propsForFixing newcaes a)) args)
print "\n Would you like me to apply the firt one? Y/N"
choice <- getLine
if(choice=="Y") then do print "applying the argument"
let applicabee = head (argumentScanHelp (head (propsForFixing newcaes a)) args)
print "Argument targeted"
let newargs = delete applicabee args
let newpargs = applicabee:nasko
print "Argument applied sucsessfuly. Recusing again"
(cip newargs newpargs burden gameover)
return()
It hurts my eyes just by looking at it, but that's do blocks for you.
Everything up to the third do block is okay. But then on this line:
if(choice=="Y") then do print "applying the argument"
let applicabee = head (argumentScanHelp (head (propsForFixing newcaes a)) args)
The complier starts crying:
Main.hs:209:73: parse error on input `let'
Tried a all kinds of different indentations but I can't seem to get it to work.
I don't want to use separate functions, because that means I'll have to pass a lot of arguments around constantly.
Can anyone help me get it right? Also an explanation of what exactly the specifications for nested do block are would be greatly appreciated.
The cause of the error I believe is the misuse of the if expression. You use it as if it were an if statement that exists in most imperative languages. Simply put there must always be an else.
However, in do blocks it makes sense to "not have an else", something like an if statement without an else. Luckily the Control.Monad module will provide you with a function for exactly that:
import Control.Monad (when)
(...)
when (choice=="Y") $ do print "applying the argument"
let applicabee = ...
You seem to already use nested do blocks in the correct way which is good, which basically is that you must indent properly.
PS. Also make sure your last return () is indented like the rest of your code! DS.