I looked into every single thread about this error message and tried everything, but it keeps disrupting the compiler.
My Code:
check2 :: Slot -> Slot -> Bool
check2 c1 c2 = if (getTime c1 == getTime c2) | (getSubject c1 == getSubject c2)
then False
else True
It throws a nice error: parse error on input ‘|’
Clarification: all tabs are 8-spaces
As you may guess, the method is part of a more larger method and was in a where clause originally. If I put it in the where clause, the parse error is on a different place, which is highly frustrating.
You should use || (the binary logical or operator, same as Java) instead of |.
You can write your function more directly this way:
check2 :: Slot -> Slot -> Bool
check2 c1 c2 = not ((getTime c1 == getTime c2) || (getSubject c1 == getSubject c2))
The | are used to define function with conditionals. For example, your own function can also be defined as:
check2 :: Slot -> Slot -> Bool
check2 c1 c2 | (getTime c1 == getTime c2) || (getSubject c1 == getSubject c2) = False
| otherwise = True
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
My task is:
Implement the function puzz. It should simulate the game similar to 15 Puzzle. In our case, we have 25 squares, where 24 squares are occupied by tiles with big case letters from 'A' to 'X'. One tile is free and is denoted by ' '. In each move, you can move a tile (denoted by its letter) into the free space. The function gets the original configuration and a sequence of valid moves. It should output the resulting configuration.
I am new to Haskell, I can only do one first move.
Result after the last move must be ["ABCDE", "FGHIJ", "KLMNO", "PQRST ", "UVWX_"]. How to save the result of the first move and use it to do the second move, and the next, and then iterate some more?
s1 = ["AC DE",
"FBHIJ",
"KGLNO",
"PQMRS",
"UVWXT"]
p1 = "CBGLMRST"
puzz :: Result -> [Char] -> Result
puzz s1 p1 =
let i = 0
p = p1 !! i
change r = [ if c == ' ' then p else if c == p then ' ' else c | c <- r ]
out = [ change r | r <- s1 ]
in out
The s1 and the p1 in the puzz s1 p1 aren't your constants s1 and p1. They are only templates. For example puzz [" B"] "B" returns ["BB "] and p1 becomes [" B"] and s1 becomes "B" in that function call.
Don't try iterate (I removed part of code with the i). Use recursion. There are no variables in Haskell, only constants and input parameters. Input parameter (represented by the template) should be in each call different (closer to the end) because of referential integrity.
Don't forget to finish the algorithm.
(p:p1) - Template of input parameter which says that there is a nonempty list and the first character will be p and tail will be p1.
puzz s1 [] = s1 - When second parametr is empty list, then return first parameter (end).
puzz out p1 - Calling puzz for the changed s1 as out and p1 from (p:p1) (recursion).
s1 = ["AC DE","FBHIJ","KGLNO","PQMRS","UVWXT"]
p1 = "CBGLMRST"
puzz :: [String] -> [Char]-> [String]
puzz s1 (p:p1) = let
change r = [ if c == ' ' then p else if c == p then ' ' else c | c <- r ]
out = [ change r | r <- s1 ]
in puzz out p1
puzz s1 [] = s1
Output:
puzz s1 p1
=> ["ABCDE","FGHIJ","KLMNO","PQRST","UVWX "]
I got the following piece of code which I know that works but I am completely new to Haskell and got 2 questions about the where clause.
f3 :: [[Int]] -> [Int] -> [Int]
f3 [] status = status --- Base Case
f3 ([p1,p2]:tail) status
| status !! (p1-1) == 0 = f3 tail status --- Case 1
| status !! (p2-1) == 1 = f3 tail newStatus1 --- Case 2
| otherwise = f3 tail newStatus2 --- Case 3
where newStatus1 = set status p1 0 --- Line 7
newStatus2 = set newStatus2Temp p1 1 --- Line 8
newStatus2Temp = set status p2 0 --- Line 9
So basically the f3 predicate has 2 arguments :
A list of Integer lists like so : [[1,2],[2,3],[3,2]]
An Integer list
It's output is the final updated second argument.
As you see besides the base case I got 2 cases (2) and (3) where the status/[Int] argument via a standard set predicate.
Question 1) :
Say case 2 is true. Does Haskell execute lines 8 and 9 ?
Say case 3 is true. Does Haskell execute line 7?
Question 2) :
Can a guard have it's own where?
Is there a better way to actually do this?
As a result of lazy evaluation, the code in each of lines 7-9 is only run if the value of the corresponding binding is evaluated/used in the course of evaluation of code for the case that matches. So:
If case 1 is true, none of lines 7-9 are run.
If case 1 is false but case 2 is true, then evaluation of newStatus runs line 7, but lines 8-9 are not run.
If cases 1 and 2 are false but case 3 is true, then evaluation of newStatus2 runs line 8 which evaluates newStatus2Temp causing line 9 to run. Line 7 is not run.
The where clauses themselves can only be attached to entire pattern bindings (e.g., the whole f3 ([p1,p2]:tail) status | ... | ... = ... expression), not individual guards, so a guard can't have its own where clause. You could either repeat the pattern for each guard:
f3 :: [[Int]] -> [Int] -> [Int]
f3 [] status = status
f3 ([p1,p2]:tail) status | status !! (p1-1) == 0 = f3 tail status
f3 ([p1,p2]:tail) status | status !! (p2-1) == 1 = f3 tail newStatus1
where newStatus1 = set status p1 0
f3 ([p1,p2]:tail) status | otherwise = f3 tail newStatus2
where newStatus2 = set newStatus2Temp p1 1
newStatus2Temp = set status p2 0
or use let ... in ... blocks:
f3 :: [[Int]] -> [Int] -> [Int]
f3 [] status = status
f3 ([p1,p2]:tail) status
| status !! (p1-1) == 0 = f3 tail status
| status !! (p2-1) == 1
= let newStatus1 = set status p1 0
in f3 tail newStatus1
| otherwise
= let newStatus2 = set newStatus2Temp p1 1
newStatus2Temp = set status p2 0
in f3 tail newStatus2
I don't think there's anything wrong with your where-clause version, and it's not unusual to write Haskell code where only a subset of the bindings in the where-clause are used (or even valid/meaningful) for each case. With such small helpers, this specific example might be more clearly written without any helpers though:
f3 :: [[Int]] -> [Int] -> [Int]
f3 [] status = status
f3 ([p1,p2]:tail) status
| status !! (p1-1) == 0 = f3 tail $ status
| status !! (p2-1) == 1 = f3 tail $ set status p1 0
| otherwise = f3 tail $ set (set status p2 0) p1 1
With GHC and -O2, all four of these (your original code and these three variants) compile to identical low-level code, so use whichever you think is clearest.
I would like to make a function in OCaml that return the position of the first and last char in a substring. For example my_sub "tar" "ar" will return (1,2) but if I have my_sub "tabr" "ar" it will be Nil, it must be consecutive. How can I do that ?
Edit
I tried to make the code but I have a problem
let rec pos_sub l t n =
let rec aux l1 l2 x =
match l1, l2 with
| [], _ | _, [] | [], [] -> -1
| h1::q1, h2 | h1, h2 -> if h1 = h2 then x else -1
| h1::q1, h2::q2 -> if h1 = h2 then aux q1 q2 x+1 else -1
in
match l, t with
| [], _ -> (-1,-1)
| h1::q1, h2::q2 -> if h1 = h2 then (n, (aux q1 q2 n+1)) else pos_sub q1 t n+1
it says :
The variable h1 on the left-hand side of this or-pattern has type 'a
but on the right-hand side it has type 'a list
The type variable 'a occurs inside 'a list
in the second match in aux
Your problem in the code is, that in this match:
| h1::q1, h2 | h1, h2 -> if h1 = h2 then x else -1
you try to compare a single character h1 with h2 which is of type string. This is what the error message tries to tell you. I think you intended match the case, where h2 is the last character of your search string, therefore:
| h1::q1, h2:[] | h1:[], h2:[] -> if h1 = h2 then x else -1
and because q1 is unused, this can then be simplified to:
| h1::_, h2:[] -> if h1 = h2 then x else -1
A sidenode: it is bad style to use -1 or similar as special values to signal error cases. Rather use optional types in such situations.
I have been trying to create a filter that checks if a phrase in a list of phrases exists in the text using recursive functions and match patterns, but somehow that does not seems to work... Maybe someone could give me hint why?
let rec matchTails (tail1 : string list) (tail2 : string list) =
match tail1, tail2 with
| h1::t1 , h2::t2 ->
if (h1=h2) then
matchTails t1 t2
else
false
| _, [] -> false
| [],_-> true
let rec check2 (textH: string) (textT: string list) (phrases: string list list) =
match phrases with
|[] -> ()
| h :: t ->
printfn "%s -- %s" (h.Head) (textH)
match h with
|x when x.Length = 1 && x.Head = textH ->
()
|x when x.Head = textH && (matchTails (textT) (x)) ->
printfn "%s" (x.Head)
| _ -> ()
check2 (textH) (textT) (t)
let rec check (phrases : string list list) (text:string list) =
match text with
| [] -> ()
| h :: t ->
check2 (h) (t) (phrases)
check phrases t
let p = [["rolex"]; ["free"; "spins"; "everyday"]; ["free"; "cash"]]
let t = ["hello";"and";"welcome";"to";"our";"annual";"free";"cash";"and";"rolex";"giveaway"]
Function call: check p t
I have edited my question with fixing few mistakes, but however, with these lists the program is giving unit() as an output...
There are some hints:
matchTails returns incorrect result for
matchTails [ "asdf1" ] [ "asdf" ] => true
matchTails [ "asdf" ] [ "asdf"; "asdf1" ] => true
matchTails [ ] [ "" ] => true
I suspect it should return false in all these cases. Probably the implementation you want is:
let rec matchTails (phrase : string list) (text : string list) =
match phrase, text with
| h1 :: t1, h2 :: t2 -> if h1 = h2 then matchTails t1 t2
else false
| [ ], _ -> true
| _ -> false
let matchTails_test () =
if not (matchTails [ "" ] [ "" ]) then raise Exception()
...
check2 is not called recursively so only the first phrase is checked
check is not called recursively, it calls check2 and returns
Generally, try to decompose problem into smaller functions and test each of them separately. You are moving in right direction, what is missing is clarity of what the each of the functions should do and test cases.
Update:
Note that check2 does not really return any value (it returns unit). Also it functionality overlaps with matchTails - it checks the head with the first word in the phrase, it is what matchTails does anyway.
check also returns unit, () means unit.
So let's rewrite check:
let rec check (phrases : string list list) (text : string list) =
if phrases |> List.exists (fun ph -> matchTails ph text) then
true
else
match text with
| [] -> false
| _ :: tail -> check phrases tail
While the question has now been basically answered, I would like to point out that its division into sub-problems is already very sufficient; shockingly lacking are the associated testing, and some descriptive naming of the individual functions tackling each sub-problem.
What about naming (and testing) matchTails, check2 and check exemplarily like this?
let ps = [["rolex"]; ["free"; "spins"; "everyday"]; ["free"; "cash"]]
let t = ["hello";"and";"welcome";"to";"our";"annual";"free";"cash";"and";"rolex";"giveaway"]
startsWithPhrase ["hello"; "and"] t
containsPhrase ["free"; "cash"] t
containsAnyPhrase ps t
Spoiler:
let rec startsWithPhrase phrase text =
match phrase, text with
| h1::t1, h2::t2 when h1 = h2 -> startsWithPhrase t1 t2
| [], _-> true
| _ -> false
let rec containsPhrase phrase text =
startsWithPhrase phrase text ||
match text with
| _::tl -> containsPhrase phrase tl
| [] -> false
let rec containsAnyPhrase phrases text =
match phrases with
| h::tl ->
containsPhrase h text ||
containsAnyPhrase tl text
| [] -> false
It may be much easier to stay completely with high-level functions, each in place of one recursive loop. Albeit here with a slighty different approach, dividing your haystack into needle-sized slices and comparing each of them with a given phrase.
let containsPhraseHL phrase text =
Seq.windowed (List.length phrase) text
|> Seq.exists (Seq.forall2 (=) phrase)
containsPhraseHL ["free"; "cash"] t
let containsAnyPhraseHL phrases text =
List.exists (fun phrase -> containsPhraseHL phrase text) phrases
containsAnyPhraseHL ps t
I'm trying to convert a column in an Excel sheet to a float in my F# application. The problem is that I do not know in which format the currency is supplied. This can be manually typed, with or without a symbol and of course the . and , symbols are always a mess.
Is there any "short and sweet" way of warsing a what appears to be incohesive array of possibilities to an actual floating point value which later after some arithmetic can be printed as currency?
A side problem I've encountered:
When a column in Excel is marked as Number 600.00 will be exported through the interop libraries as 600; 534.20 will be exported as 534.2
A simple parse on the . symbol is not enough.
The symbol which is not shown is Excel will be exported through the interop libraries as a ? (with a space following).
These options do not wor:
let ParseFloat1 (o:obj) =
float (o.ToString())
let parseFloat2 (o:obj) =
float (System.Single.Parse(o.ToString()))
After these attempts I just went crazy and started russamafuzzin' solutions, not even this dragon of a bad idea worked:
let ParseFloat o =
// ugly
let mutable _string = o.ToString()
// because of the weird "lets leave trailing zero's off behavior
let changeString (s:string) =
match s.LastIndexOf "." with
| 0 | -1 -> s + "00"
| 1 -> s + "0"
| _ -> s
_string <- changeString _string
let characters = _string.ToCharArray()
// remove all the non numbers from the string
let rec parse source dest =
match source with
| h::t ->
match h with
| '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0' -> parse t (dest + h.ToString())
| _ -> parse t dest
| _ -> dest
let _float = parse (Array.toList characters) ""
let result = (float (System.Single.Parse(_float))) / (float 100)
result
I really hope someone can help me, because this is driving me crazy. Thank you in advance.
EDIT (16-11-2015):
More information after the valid comments, I appreciate all the help and comments.
I have broken the issue down into more "parts" so I've introduced a few conventions for this application. I figured that there is no solution for the problem so I needed to put in some restrictions and hope for the best...
I get the decimal symbol from CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator and make sure the column in the excel sheet is of type Number, adding a column of this type and resaving if needed.
I remove all the other symbols from the string, leaving only the separator in place. (Just like the answer Petr)
Running Excel in same context and app making sure the CultureInfo is the same.
To expand on Petr's answer:
let ParseFloat o =
let decimalSeparator = Convert.ToChar(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
let newv = String((o.ToString()) |> Seq.filter (fun c -> Char.IsNumber c || c = decimalSeparator) |> Array.ofSeq )
let rslt = match Double.TryParse(newv) with
| true, number -> (float number)
| false, _ -> throw "Cannot parse the number"
rslt
Something like this?
open System
let value = "£1,097."
let newv = String(value |> Seq.filter (fun c -> Char.IsNumber c || c = '.') |> Array.ofSeq )
let rslt = match Double.TryParse(newv) with
| true, number -> printfn"Converted '%s' to %.2f" value number
| false, _ -> printfn "Unable to convert '%s'" value
Result:
Converted '£1,097.' to 1097.00