here are some type definitions in my program FYI:
type BitString -> String
type Plateau -> [BitString]
I have a function called:
--Extract will take a list of lists, and return the inner list of the most items. Empty list should return ["00000"]
extract::[Plateau]->Plateau
extract _ = ["00000"]
extract (x:xs)
|x==maximumBy(compare `on` length)xs=x --thanks SOF
|otherwise = extract (xs)
The problem is, no matter what i do, extract returns ["00000"]
here are some outputs from GHCI, that are working:
>plateau graycodes
[["01000"],["01010","11010","10010"],["00101"],["01101","01001"]]
this is expected, and is in the form of a [Plateau] since this is a list of lists of string.
>maximumBy(compare `on` length)(plateau graycodes)
["01010","11010","10010"]
>extract (plateau graycodes)
["00000"]
in this case, i know for sure that extract will be called with a not empty [Plateau]. But the _ part of the function is returning.
I have tried also:
extract (x:xs)
|x==[]=["00000"]
|x==[""]=["00000"]
|x==maximumBy(compare `on` length)xs=x --thanks SOF
|otherwise = extract (xs)
error: List.maximumBy: Empty list
When you define a function with multiple patterns, they will be tried in order from top to bottom. The problem is that your topmost pattern of extract will match anything, and therefore the first case will always be chosen.
The solution is to either reorder them, or change the first pattern to only match the empty list:
extract [] = ["00000"]
extract (x:xs) = ...
you are getting that error, because you are not passing in your list (x:xs) to maximumBy:
extract :: [Plateau] -> Plateau
extract (x:xs)
|x == maximumBy (compare `on` length) (x:xs) = x
|otherwise = extract (xs)
extract _ = ["00000"]
or, preferably,
extract :: [Plateau] -> Plateau
extract s#(x:xs)
|x == maximumBy (compare `on` length) s = x
|otherwise = extract (xs)
extract _ = ["00000"]
(this also adds a needed = after your otherwise)
EDIT:
I was not satisfied with my answer, or your acceptance of that answer.
I believe this is the code you are really after:
extract :: [Plateau] -> Plateau
extract (x:[]) = x
extract s#(x:xs) = maximumBy (compare `on` length) s
extract _ = ["00000"]
The solution is simple, switch place of the cases of extract. The pattern extract _ will always match,
thus the second case will never be executed.
Working code (hopefully):
--Extract will take a list of lists, and return the inner list of the most items. Empty list should return ["00000"]
extract::[Plateau]->Plateau
extract (x:xs)
|x==maximumBy(compare `on` length)=x --thanks SOF
|otherwise extract (xs)
extract _ = ["00000"]
Related
I am trying to implement a list, which searches for a certain pattern in a Tuple (goes through the list of Tuples, empties this and then writes those in, which match the pattern) in the end the list I entered will be empty and then it writes the matching Tuples in this list.
(The functions used do all work - the mistake is in this part)
PatternFinder :: String -> [(String, String)] , [(String, String)]
PatternFinder = n ((b,a) : xs) =
if PatternFits n a
then do
PatternFinder n xs
(b,a) : xs
else PatternFinder n xs
From the text of your question, it seems like you want a simple filter based on the second term of each pair.
patternFinder n = filter (patternFits n . snd)
As an illustration of how this works.
filter ((==1) . snd) [('a',1),('b',2),('c',1)]
returns [('a',1),('c',1)]
In Chad Gilberts answer, however, there is no recursion in the then clause:
if patternFits n a
then (b,a) : xs
else patternFinder n xs
This will return the suffix of the list after the first match. If this is the intended behavior, you could use instead:
patternFinder n = dropwhile (not . patternFits n . snd)
As an example of this:
dropWhile (not . (==2) . snd) [('a',1),('b',2),('c',1)]
returns [('b',2),('c',1)]
Also, in the text of your question you require that the list you entered will be empty. Note that these functions do nothing to the original list but return new lists.
You are not the case of the second argument being the empty list. In order to be exhaustive, you have to handle this pattern:
patternFinder n []
You've also got other syntax errors. Function names must start with a lowercase letter, signatures are separated by ->, not ,, and you don't need a do statement because you're not in a monad context. It should probably look more like this:
patternFinder :: String -> [(String, String)] -> [(String, String)]
patternFinder n [] = []
patternFinder n ((b,a) : xs) =
if patternFits n a
then (b,a) : xs
else patternFinder n xs
I have made function that takes a list and a list of lists and returns a new list of lists.
let rec calculator list SS =
match (List.item(0) SS) with
|[] -> []
|_ -> match (validate list (List.item(0) SS)) with
|(validate theCode list) -> List.append [(List.item(0) SS)] (calculator list (SS.[1..]))
|_ -> (calculator list (SS.[1..]))
validate is a function that returns two tupled ints. example (1,1)
list is a list of four ints
SS is a list of lists with four ints
theCode is a list of four ints
i get the error "The pattern discriminator 'validate' is not defined."
Perhaps this is a silly question but none the less i don't know the answer to it.
Is it not allowed to use a function as an argument in a match expression. Or is it something entirely different going on here?
to the best of my knowledge the two validate functions will return two tupled ints and therefore should be able to match upon that.
If your question is how to get this to compile then you only need a small change – a function call is not itself a pattern, so you need to bind to a value and use a when guard:
let rec calculator list SS =
match (List.item(0) SS) with
| [] -> []
| _ ->
match (validate list (List.item(0) SS)) with
// vvvvvvvvvv
| x when x = (validate theCode list) ->
List.append [(List.item(0) SS)] (calculator list (SS.[1..]))
| _ -> (calculator list (SS.[1..]))
However, if your question is indeed "what is the preferred method", then while that's too subjective for this site (IMO), I'll submit this as an option that I consider ideally readable for this logic:
let rec calculator list (h::t) =
if List.isEmpty h then h
elif validate list h = validate theCode list then h::(calculator list t)
else calculator list t
(This assumes that SS is an F# list and not a System.Collections.Generic.List.)
This is not actually an answer to the question of how to implement the when guard, since #ildjarn answered that for you.
I think you'd actually be better served by a library function. What you're trying to do appears to be to filter out elements which don't pass validation, but also to stop on the first empty element. If you can guarantee that you definitely want to loop through every element of SS, you could simply do
let calculator list = List.filter (fun s -> validate list s = validate theCode list)
If it's you must stop at the empty element, you could define a function that cuts the list at the first empty element, something like
let upToElement element list =
let rec loop acc = function
| [] -> List.rev acc
| h :: t when h = element -> List.rev acc
| h :: t -> loop (h :: acc) t
loop [] list
then you can do
let calculator list =
upToElement [] >> List.filter (fun s -> validate list s = validate theCode list)
I'm new to F# and I'm trying to write a method split that splits a list into 2 pieces. It takes a tuple with the first element being the number of elements to split and the second element is the list . For example, split (2, [1;2;3;4;5;6]) should return ([1;2], [3;4;5;6]),
This is what I have so far, but for some reason it is returning the second element of the tuple as the original list without the head. I don't understand this because I thought that x::xs automatically makes x the head element and xs the rest of the list, which would mean that each recursive call is taking the tail of the previous list and chopping off the first term.
let rec split = function
|(n, []) -> ([], [])
|(0, xs) -> ([], xs)
|(n, x::xs) -> let temp = x :: fst (split(n-1, xs))
(temp, xs);;
The problem is on this line:
(temp,xs);;
here in your example, xs will always be [2;3;4;5;6] as long as n>0
You need to get the second element of the list with something like
|(n,x::xs) ->
let a,b = split (n-1,xs)
(x::a,b)
I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.
Inspired by Comparing list length
If I want to find the longest list in a list of lists, the simplest way is probably:
longestList :: [[a]] -> [a]
longestList = maximumBy (comparing length)
A more efficient way would be to precompute the lengths:
longest :: [[a]] -> [a]
longest xss = snd $ maximumBy (comparing fst) [(length xs, xs) | xs <- xss]
Now, I want to take it one step further. It may not be more efficient for normal cases, but can you solve this using arrows? My idea is basically, step through all of the lists simultaneously, and keep stepping until you've overstepped the length of every list except the longest.
longest [[1],[1],[1..2^1000],[1],[1]]
In the forgoing (very contrived) example, you would only have to take two steps through each list in order to determine that the list [1..2^1000] is the longest, without ever needing to determine the entire length of said list. Am I right that this can be done with arrows? If so, then how? If not, then why not, and how could this approach be implemented?
OK, as I was writing the question, it dawned on me a simple way to implement this (without arrows, boo!)
longest [] = error "it's ambiguous"
longest [xs] = xs
longest xss = longest . filter (not . null) . map (drop 1) $ xss
Except this has a problem...it drops the first part of the list and doesn't recover it!
> take 3 $ longest [[1],[1],[1..2^1000],[1]]
[2,3,4]
Needs more bookkeeping :P
longest xs = longest' $ map (\x -> (x,x)) xs
longest' [] = error "it's ambiguous"
longest' [xs] = fst xs
longest' xss = longest . filter (not . null . snd) . map (sndMap (drop 1)) $ xss
sndMap f (x,y) = (x, f y)
Now it works.
> take 3 $ longest [[1],[1],[1..2^1000],[1]]
[1,2,3]
But no arrows. :( If it can be done with arrows, then hopefully this answer can give you someplace to start.
Thinking about this some more, there is a far simpler solution which gives the same performance characteristics. We can just use maximumBy with a lazy length comparison function:
compareLength [] [] = EQ
compareLength _ [] = GT
compareLength [] _ = LT
compareLength (_:xs) (_:ys) = compareLength xs ys
longest = maximumBy compareLength
Here's the most straightforward implementation I could think of. No arrows involved, though.
I keep a list of pairs where the first element is the original list, and the second is the remaining tail. If we only have one list left, we're done. Otherwise we try taking the tail of all the remaining lists, filtering out those who are empty. If some still remain, keep going. Otherwise, they are all the same length and we arbitrarily pick the first one.
longest [] = error "longest: empty list"
longest xss = go [(xs, xs) | xs <- xss]
where go [(xs, _)] = xs
go xss | null xss' = fst . head $ xss
| otherwise = go xss'
where xss' = [(xs, ys) | (xs, (_:ys)) <- xss]