TareaHaskell.hs:36:69: error: parse error on input ')' - parsing

This is my first time trying Haskell. I'm trying to make a function that takes an element and a list and removes the second appearance of the item. For example, if the element is 2 and the list is [2,3,4,2,5,2] the result would be [2, 3, 4, 5, 2].
However I am getting this error:
TareaHaskell.hs:36:69: error: parse error on input ‘)’
|
36 | | ( (a == x) && not (isItIn x newList) ) = ( (let newList = x:[]) && (deleteSecond a xs) )
Code:
isItIn :: (Eq a ) => a -> [a] -> Bool
isItIn a [] = False
isItIn a (x:xs) = if a == x
then True
else isItIn a xs
deleteSecond :: (Eq a ) => a -> ( [a] -> [a] )
deleteSecond a [] = newList
deleteSecond a (x:xs)
| ( (a == x) && not (isItIn x newList) ) = ( (let newList = x:[]) && (deleteSecond a xs) )
| (a == x) && (isItIn x newList) = (deleteSecond a xs)
| otherwise = let newList = x:[] && deleteSecond a xs
I read it might be a problem with the indentation however I already tried using spaces, moving it back and forth, and it still isn't working.
I am also using Notepad++ and Sublime to help with the indentation and nothing.

The problem is that the parser isn't expecting the ) in this code:
(let newList = x:[])
because it's invalid in Haskell to have a let statement that isn't followed by in. (With the exception of inside a do block.)
It's really not clear to me what your actual intention is, but all let is for is to give a more complex expression a temporary name inside a block of code. A let statement without an accompanying in doesn't make any sense, and is causing your parse error here.

Your code is a little over complicated. If you simplified it'd be more clear where the problem is, but
let newList = x:[]
is only valid if the next symbol is in. The parser is complaining that you're trying to parenthesize it for no reason. A let..in statement is just a way of temporarily binding a name to a value for the purpose of the expression.
let var = value in expr
As far as the problem itself: this is pretty easy to solve with explicit recursion.
removeSecond :: (Eq a) -> [a] -> [a]
removeSecond = go False
where go _ _ [] = []
go True needle (x:xs) | needle == x = xs
| otherwise = x : go True needle xs
go False needle (x:xs) | needle == x = x : go True needle xs
| otherwise = x : go False needle xs

Related

can I group option checks in F#

I have the following code:
let i = instrumentFromString arguments.[1]
let o = podManager.GetExchange().GetLeverageOptions(i.Value)
let l = parseInt arguments.[2] |> Option.bind (fun x -> if i.IsSome && o |> List.contains(x) then Some x else None)
let wl = parseDecimal arguments.[3] |> Option.bind (fun x -> if x > 0m && x <= 1m then Some x else None)
let ws = parseDecimal arguments.[4] |> Option.bind (fun x -> if x > 0m && x <= 1m then Some x else None)
it's parsing commands entered into the system.
it's then followed by:
match i.IsSome && l.IsSome && wl.IsSome && ws.IsSome with
| true ->
... do stuff
| false ->
stringBuffer {
if i.IsNone then $"unkown instrument 'arguments.[1]'\n"
if l.IsNone && i.IsSome then $"invalid leverage, instrument '{i.Value.Ticker}' supports {podManager.GetExchange().GetLeverageOptions(i.Value)}\n"
if wl.IsNone then $"invalid long share, must be > 0 and <= 1\n"
if ws.IsNone then $"invalid short share, must be > 0 and <= 1\n"
}
and I feel like it is a bit convoluted because I parse the arguments, then verify them, then make sure they're all ok and if they're not, I'm going through them one by one again.
so an option would be to transform the parsing lines like this:
let l = parseInt arguments.[2] |> Option.bind (fun x -> if i.IsSome && o |> List.contains(x) then Result.Ok x else Result.Error "my error message")
so it would group the test and error message, but I still have to check if there is any error, and then parse the possible errors one by one again.
I guess a computation expression where I can accumulate both the ok / error values could work, but there is the issue of the Option / Result conversion as well.
Is there some nice idiomatic way to handle this kind of scenario that I missed?
I recommend you convert your options to results and use the validation builder in FsToolkit.ErrorHandling. This uses F# 5 language features. You can try out this code in an F# script:
#r "nuget: FsToolkit.ErrorHandling,2.0.0"
open FsToolkit.ErrorHandling
let a : Result<string, string> = Ok "a"
let b : Result<string, string> = Error "b missing"
let c : Result<string, string> = Ok "c"
let d : Result<string, string> = Error "d missing"
validation {
let! a = a
and! b = b
and! c = c
and! d = d
return a, b, c, d
}
// Returns: Error ["b missing"; "d missing"]
You should be able to apply this example to your code.

F# : How to test the equality of sequence/list elements?

I would like to test whether all of elements in a list/sequence equals something
For example,a sequence of integers.
I would like to test if ALL element of the sequence equals to the same number.
My solution so far looks like imperative programming solution.
let test seq =
if Seq.forall(fun num -> num =1) then 1
elif Seq.forall(fun num-> num = 2) then 2
else None
Your solution is fine! Checking that all elements of a sequence have some value is not something you can nicely express using pattern matching - you have to use when clause, but that's doing exactly the same thing as your code (but with longer syntax). In cases like this, there is absolutely nothing wrong with using if.
You can extend pattern matching by definining custom active patterns, which gives you a nice option here. This is fairly advanced F#, but you can define a custom pattern ForAll n that succeeds when the input is a sequence containing just n values:
let (|ForAll|_|) n seq =
if Seq.forall (fun num -> num = n) seq then Some() else None
Note that success is represented as Some and failure as None. Now, you can solve your problem very nicely using pattern matching:
let test = function
| ForAll 1 -> Some 1
| ForAll 2 -> Some 2
| _ -> None
This looks quite nice, but it's relying on more advanced features - I would do this if this is something that you need in more than one place. If I needed this just in one place, I'd go with ordinary if.
You can rewrite it using pattern matching with a guard clause:
let testList = [2;2;2]
let isOne x = x = 1
let isTwo x = x = 2
let forAll = function
| list when list |> List.forall isOne -> Some 1
| list when list |> List.forall isTwo -> Some 2
| _ -> None
let res = forAll testList //Some 2
Instead of the function you could use partial application on the equals operator.
> let yes = [1;1;1];;
val yes : int list = [1; 1; 1]
> let no = [1;2;3];;
val no : int list = [1; 2; 3]
> yes |> List.forall ((=) 1);;
val it : bool = true
> no |> List.forall ((=) 1);;
val it : bool = false
Maybe this looks more functional? And I think you should return Some 1 in your code, otherwise you'd get type errors since Option and int are not the same type...
If you want to check if all elements are equal (not just if they equal some constant), you could do this:
> [1;2] |> List.pairwise |> List.forall (fun (a,b) -> a = b)
;;
val it : bool = false
> [1;1;1] |> List.pairwise |> List.forall (fun (a,b) -> a = b)
;;
val it : bool = true
There you split your list into tuples and checks if the tuples are equal. This means transitively that all elements are equal.

Break the iteration and got the values and states?

I need to call a function on each item in the list; and quit immediately if the function returns -1. I need to return the sum of results of the function and a string of "Done" or "Error".
let input = seq { 0..4 } // fake input
let calc1 x = // mimic failing after input 3. It's a very expensive function and should stop running after failing
if x >= 3 then -1 else x * 2
let run input calc =
input
|> Seq.map(fun x ->
let v = calc x
if v = -1 then .... // Error occurred, stop the execution if gets -1. Calc will not work anymore
v)
|> Seq.sum, if hasError then "Error" else "Done"
run input calc // should return (6, "Error")
run input id // should return (20, "Done")
The simplest way to effectively achieve exactly what is asked in idiomatic manner would be to use of an inner recursive function for traversing the sequence:
let run input calc =
let rec inner unprocessed sum =
match unprocessed with
| [] -> (sum, "Done")
| x::xs -> let res = calc x
if res < 0 then (sum, "Error") else inner xs (sum + res)
inner (input |> Seq.toList) 0
Then run (seq {0..4}) (fun x -> if x >=3 then -1 else x * 2) returns (6,"Error") while
run (seq [0;1;2;1;0;0;1;1;2;2]) (fun x -> if x >=3 then -1 else x * 2) returns (20, "Done")
More efficient version of the same thing shown below. This means it is now essentially a copy of #GeneBelitski's answer.
let run input calc =
let inputList = Seq.toList input
let rec subrun inp acc =
match inp with
| [] -> (acc, "Done")
| (x :: xs) ->
let res = calc x
match res with
| Some(y) -> subrun xs (acc + y)
| None -> (acc, "Error")
subrun inputList 0
Note that this function below is EXTREMELY slow, likely because it uses Seq.tail (I had thought that would be the same as List.tail). I leave it in for posterity.
The easiest way I can think of for doing this in F# would be to use a tail-recursive function. Something like
let run input calc =
let rec subrun inp acc =
if Seq.isEmpty inp then
(acc, "Done")
else
let res = calc (Seq.head inp)
match res with
| Some(x) -> subrun (Seq.tail inp) (acc + x)
| None -> (acc, "Error")
subrun input 0
I'm not 100% sure just how efficient that would be. In my experience, sometimes for some reason, my own tail-recursive functions seem to be considerably slower than using the built-in higher-order functions. This should at least get you to the right result.
The below, while apparently not answering the actual question, is left in just in case it is useful to someone.
The typical way to handle this would be to make your calc function return either an Option or Result type, e.g.
let calc1 x = if x = 3 then None else Some(x*2)
and then map that to your input. Afterwards, you can fairly easily do something like
|> Seq.exists Option.isNone
to make see if there are Nones in the resulting seq (you can pipe it to not if you want the opposite result).
If you just need to eliminate Nones from the list, you can use
Seq.choose id
which will eliminate all Nones while leaving the Options intact.
For summing the list, assuming that you have used choose to be left with just the Somes, then you can do
Seq.sumBy Option.get
Here is a monadic way of doing it using the Result monad.
First we create function calcR that if calc returns -1 returns Error otherwise returns Ok with the value:
let calcR f x =
let r = f x
if r = -1 then Error "result was = -1" else
Ok r
Then, we create function sumWhileOk that uses Seq.fold over the input, adding up the results as long as they are Ok.
let sumWhileOk fR =
Seq.fold(fun totalR v ->
totalR
|> Result.bind(fun total ->
fR v
|> Result.map (fun r -> total + r)
|> Result.mapError (fun _ -> total )
)
) (Ok 0)
Result.bind and Result.map only invoke their lambda function if the supplied value is Ok if it is Error it gets bypassed. Result.mapError is used to replace the error message from calcR with the current total as an error.
It is called this way:
input |> sumWhileOk (calcR id)
// returns: Ok 10
input |> sumWhileOk (calcR calc1)
// return: Error 6

Parenthesis Matching F#

So I am trying to use f# to find if a string has matching parentheses.
i.e: (abc) returns true, ((hello) returns false, and )( returns false, etc...
What I (think) am doing is using a stack to push when it sees a '(' and pop when it sees a ')' in the list. Then if the string list is empty, either the stack has an item or it doesn't. If it does, then I say that it is invalid, if I come across a ')' and the stack is empty, it is also invalid. Otherwise it is a valid string.
// Break string
let break_string (str:string) =
Seq.toList str
let isBalanced (str:string) =
let lst = break_string str
let stack = []
let rec balance str_lst (stk:'a list)=
match str_lst with
| [] ->
if stk.Length > 0 then
false
else
true
| x::xs ->
if x = '(' then
balance (xs x::stack)
elif x = ')' then
if stack.Length = 0 then
false
else
stack = stack.tail
balance (lst, stack)
I am pretty new to f# so I think this might be doing what I want, however I get the error message:
"This expression was expected to have type bool but here has type 'a list -> bool"
First, what does that actually mean?
Second, since it is returning a bool, why doesn't that work?
The type-checker thinks you forgot the second argument to balance. When you write this:
balance (xs x::stack)
It means "apply balance to (apply xs to x::stack)". You probably meant this:
balance xs (x::stack)
Your final elif also seems to be missing an else branch, and the line stack = stack.tail looks like you're trying to assign to stack. You can't do that since stack is an immutable variable. Likely you want balance xs (List.tail stack). The principle is that instead of assigning to variables, you call your function with new values.
You have the right idea, of course. It can be much more concise by folding all the matching (what's the letter? what's on the stack?) into one single match statement. The trick is to put all the things you want to look at into a single tuple:
let isBalanced str =
let rec loop xs stack =
match (xs, stack) with
| '(' :: ys, stack -> loop ys ('(' :: stack)
| ')' :: ys, '(' :: stack -> loop ys stack
| ')' :: _, _ -> false
| _ :: ys, stack -> loop ys stack
| [], [] -> true
| [], _ -> false
loop (Seq.toList str) []

megaparsec reports incorrect location on parse error

For this project I'm parsing in two stages. The first stage handles include/ifdef/define directives and chunks the input up into [Span] items which define their start/end points in the original inputs along with the body text. This stream is then parsed by the second stage into my AST for subsequent processing.
Each element of the AST carries it's source position and any semantic error caught after parsing prints the correct error position regardless of include depth. This part is crucial since it comes after the stage that has the problem.
The problem is given a parse error in the second stage from an included file it reports a bogus error with a location at the top level rule in the input. A parse error in the initial file works fine. The presence of any directives will divide even the initial file into multiple chunks so it's not a 'single chunk' vs. 'multiple chunks' issue.
Given the fact that the AST is getting the locations correct I'm stumped as to how Megaparsec is reporting bad info when parse errors are encountered.
I'm included my stream instance and (set|get)(Position|Input) code since these seem like the relevant bits. i feel like there must be some bit of megaparsec housekeeping that I'm not doing or that my Stream instance is invalid for some reason.
data Span = Span
{ spanStart :: SourcePos
, spanEnd :: SourcePos
, spanBody :: T.Text
} deriving (Eq, Ord, Show)
instance Stream [Span] where
type Token [Span] = Span
type Tokens [Span] = [Span]
tokenToChunk Proxy = pure
tokensToChunk Proxy = id
chunkToTokens Proxy = id
chunkLength Proxy = foldl1 (+) . map (T.length . spanBody)
chunkEmpty Proxy = all ((== 0) . T.length . spanBody)
positionAt1 Proxy pos (Span start _ _) = trace ("pos1" ++ show start) start
positionAtN Proxy pos [] = pos
positionAtN Proxy _ (Span start _ _:_) = trace ("posN" ++ show start) start
advance1 Proxy _ _ (Span _ end _) = end
advanceN Proxy _ pos [] = pos
advanceN Proxy _ _ ts = let Span _ end _ = last ts in end
take1_ [] = Nothing
take1_ s = case takeN_ 1 s of
Nothing -> Nothing
Just (sp, s') -> Just (head sp, s')
takeN_ _ [] = Nothing
takeN_ n s#(t:ts)
| s == [] = Nothing
| n <= 0 = Just ([t {spanEnd = spanStart t, spanBody = ""}], s)
| n < (T.length . spanBody) t = let (l, r) = T.splitAt n (spanBody t)
sL = spanStart t
eL = foldl (defaultAdvance1 (mkPos 3)) sL (T.unpack (T.tail l))
sR = defaultAdvance1 (mkPos 3) eL (T.last l)
eR = spanEnd t
l' = [Span sL eL l]
r' = (Span sR eR r):ts
in Just (trace (show n) l', r')
| n == (T.length . spanBody) t = Just ([t], ts)
| otherwise = case takeN_ (n - T.length (spanBody t)) ts of
Nothing -> Just ([t], [])
Just (t', ts') -> Just (t:t', ts')
takeWhile_ p s = fromJust $ takeN_ (go 0 s) s
where go n s = case take1_ s of
Nothing -> n
Just (c, s') -> if p c
then go (n + 1) s'
else n
Find include and swap to it:
"include" -> do
file <- between dquote dquote (many (alphaNumChar <|> char '.' <|> char '/' <|> char '_'))
s <- liftIO (Data.Text.IO.readFile file)
p <- getPosition
i <- getInput
pushPosition p
stack %= (:) (p, i)
setPosition (initialPos file)
setInput s
And if we reach the end of input pop stack and continue:
parseStream' :: StreamParser [Span]
parseStream' = concat <$> many p
where p = do
b <- tick <|> block
end <- option False (True <$ hidden eof)
h <- use stack
when (end && (h /= [])) $ do
popPosition
setInput (h ^?! ix 0 . _2)
stack %= tail
return b

Resources