im in the process of writing a transposing recursive function and i have stopped at a problem. So i want to have a check using match by calling isTable function to verify that the input M is a valid table, however it errors and im not sure how to fix it
let isTable list =
match List.map List.length list |> List.distinct |> List.length with
| 1 -> true
| _ -> false
let rec transpose M =
match M with
| []::_ -> []
| (isTable M) -> [] // i want to check here if M is a valid table
| _ -> (List.map List.head M::transpose(List.map List.tail M))
error FS0039: The pattern discriminator 'isTable' is not defined.
Active patterns are one approach, but the overhead of adding one just for a single use is not worth it. An easy and uncluttered solution would be to use a when clause:
let rec transpose M =
match M with
| []::_ -> []
| _ when isTable M -> []
| _ -> (List.map List.head M::transpose(List.map List.tail M))
None of the answers yet show how to turn your case into an Active Pattern. This is particularly useful for (1) readability and (2) reusability of code. Assuming you'd need isTable more than once, this can be beneficial.
/// Active pattern, must start with capital letter.
let (|IsTable|_|) list =
match List.map List.length list |> List.distinct with
| [_] -> Some list
| _ -> None
let rec transpose M =
match M with
| []::_ -> []
| IsTable M -> [] // using the active pattern
| _ ->
List.map List.head M::transpose(List.map List.tail M)
As an aside, your isTable function matched over List.length result. A List.length iterates over the whole list and is O(n). Since we're only interested if the result is one item, the above approach will be more efficient, removing at least one iteration from the code.
Try something like
let rec transpose M =
match M with
| []::_ -> []
| _ -> match (isTable M) with
| true - > [] // i want to check here if M is a valid table
| _ -> (List.map List.head M::transpose(List.map List.tail M))
As a matter of programming style I'd recommend adding a data constructor like Table so that you can match on it but this should get things working.
I want to do a Haskell function where the input (a list of Strings) is ordered (always. input is valid only if is ordered) and I want to get the number of occurrences of each different string.
Example:
ContaOcs["a", "a", "b", "c", "c", "c", "d"]
Should return:
[(2,"a"), (1,"b"), (3,"c"), (1,"d")]
Here is What I'm trying to do:
module Main where
contaOcs :: [String] -> [(Int, String)]
contaOcs [] = [_,_]
contaOcs [x] = [1,x]
contaOcs (i, x1:x2:xs)
| x1 == x2 = (i+1,(x2:xs))
| otherwise = (0, (x2:xs))
But this code have some errors and I'm not so sure how I should do to accomplish this
I'm new to functional programing and Haskell. Can anyone help me with some information?
Thanks for any help.
There are some syntactical problems as well as problems with the types. The first line looks like:
contaOcs [] = [_,_]
But an underscore (_) in the result does not makes any sense, you can only construct lists with values in it. When we count the number of occurences of an empty list, the result will be an empty list, so contaOcs [] = [].
As for the second:
contaOcs [x] = [1,x]
Here you aim to return a list with two elements: a 1 and an x (which is a String). In Haskell the elements of a list all have the same type. What you can do is return a list of 2-tuples with the first item an Int, and the second a String, like the signature suggests, but then you need to wrap the values in a 2-tuple, like contaOcs [x] = [(1,x)].
In your last clause, you write:
contaOcs (i, x1:x2:xs) = ...
which does not make much sense: the input type is a list (here of Strings), not a 2-tuple with an Int, and a list of strings.
So the input will look like:
contaOcs (x1:x2:xs) = ...
The output, like (i+1,(x2:xs)) also is not in "harmony" with the proposed output type in the signature, this looks like a 2-tuple with an Int, and a list of Strings, so (Int, [String]), not [(Int, String)].
Based on the above comments, we have derived something like:
contaOcs :: [String] -> [(Int, String)]
contaOcs [] = []
contaOcs [x] = [(1,x)]
contaOcs (x1:x2:xs)
| x1 == x2 = -- ...
| otherwise = -- ...
So now there are two parts to fill in. In case x1 and x2 are not equal, that means that we can first yield a tuple (1, x1) in the list, followed by the result of contaOcs on the rest of the list (x2 included), so:
(1, x1) : contaOcs (x2:xs)
In the latter case, it means that we first make a recursive call to contaOcs with (x2:xs), and then increment the counter of the first item of that list. We are sure such element exists, since we make a recursive call with a list containing at least one element, and by induction, that means the result contains at least one element as well, since the base case contains one element, and the recursive case either prepends elements to the result, or updates these.
So we can use a pattern guard, and maniplate the result, like:
contaOcs :: [String] -> [(Int, String)]
contaOcs [] = []
contaOcs [x] = [(1,x)]
contaOcs (x1:x2:xs)
| x1 == x2, ((yi, yv):ys) <- contaOcs (x2:xs) = (yi+1, yv) : ys
| otherwise = (1, x1) : contaOcs (x2:xs)
We can also use an "as-pattern": we only need a reference to the tail of the list starting with x2, not xs:
contaOcs :: [String] -> [(Int, String)]
contaOcs [] = []
contaOcs [x] = [(1,x)]
contaOcs (x1:xs#(x2:_))
| x1 == x2, ((yi, yv):ys) <- contaOcs xs = (yi+1, yv) : ys
| otherwise = (1, x1) : contaOcs xs
The above is however not very elegantly. It might be better to use an accumulator here, I leave this as an exercise.
Let's look at some of the errors mentioned by ghc. Always pay close attention to when GHC talks about Expected and Actual types, as these messages are always illuminating. Expected indicates what GHC thinks you should write. Actual indicates what you wrote. You either need to change what you wrote (read: change your code), or change what GHC thinks you should write (read: change your type annotations). In this case it's mostly the former.
hw.hs:2:16: error:
• Found hole: _ :: (Int, String)
• In the expression: _
In the expression: [_, _]
In an equation for ‘contaOcs’: contaOcs [] = [_, _]
• Relevant bindings include
contaOcs :: [String] -> [(Int, String)] (bound at hw.hs:2:1)
|
2 | contaOcs [] = [_,_]
| ^
hw.hs:2:18: error:
• Found hole: _ :: (Int, String)
• In the expression: _
In the expression: [_, _]
In an equation for ‘contaOcs’: contaOcs [] = [_, _]
• Relevant bindings include
contaOcs :: [String] -> [(Int, String)] (bound at hw.hs:2:1)
|
2 | contaOcs [] = [_,_]
| ^
The underscore is used as a placeholder (or "hole"), to be filled in later. GHC is telling you that you should figure out something to put in these holes.
hw.hs:3:19: error:
• Couldn't match type ‘[Char]’ with ‘(Int, String)’
Expected type: (Int, String)
Actual type: String
• In the expression: x
In the expression: [1, x]
In an equation for ‘contaOcs’: contaOcs [x] = [1, x]
|
3 | contaOcs [x] = [1,x]
|
You have declared that the return type of the function is [(Int, String)], in other words, a List, where each element of the list is a Tuple of Int and String.
Therefore, each element in the list should be a Tuple. The syntax [1,x] means a list with two elements: 1 and x. GHC has noticed that x, however, is known to be a String, which is not a Tuple. (GHC failed to notice that 1 is not a tuple, for... reasons. Numbers in Haskell are a little weird and GHC is not so helpful with those.)
Perhaps you meant to write (1, x), which is a tuple of 1 (an Int) and x (a String). However, don't forget to also put that tuple into a list somehow, since your return type is a list of tuples.
hw.hs:4:10: error:
• Couldn't match expected type ‘[String]’
with actual type ‘(Integer, [a0])’
• In the pattern: (i, x1 : x2 : xs)
In an equation for ‘contaOcs’:
contaOcs (i, x1 : x2 : xs)
| x1 == x2 = (i + 1, (x2 : xs))
| otherwise = (0, (x2 : xs))
|
4 | contaOcs (i, x1:x2:xs)
| ^^^^^^^^^^^^^
GHC is again reminding you that it expects a list of tuples, but in this case, you gave it just one tuple.
The errors are mostly the same as this.
contaOcs :: [String] -> [(Int, String)]
contaOcs consumes a list of strings: xss, for each unique string: xs in xss, we produce a pair: p, whose first element represents the number of occurrences of xs in xss, and the second element of p is that xs itself.
We know we need to group strings by their uniqueness and count each unique string's total occurrences. You can follow this idea and implement the rest yourself. contaOcs takes a list and produces a new list so list comprehension should give you what you want. You're transforming one list to another, so fmap a function that accumulates should work. You can also just use natural recursion or accumulator. Here is one way to write contaOcs:
contaOcs = (return . liftA2 (,) length head =<<) . group
Write down the signature, purpose statement, some sample data and test cases first, then it's just a matter of finding the solutions that best fit your need.
This is a good example of when a co-recursive function is helpful.
contaOcs :: [String] -> [(Int, String)]
We'll define contaOcs as the outer function that takes the list of strings and returns the tuples. First let's look at the trivial cases:
contaOcs [] = []
contaOcs [x] = [(1,x)]
Pass an empty list, and you should get back an empty list. Pass a single element list, and you should get back a list with one element: (1, x). Now we can guarantee that any other list is 2+ elements long.
contaOcs (x:xs) = go x xs
go? What is go you might ask? Well let's define it in the where clause:
where
go cur xs = let (this, rest) = span (==x) xs
in (succ . length $ this, cur) : contaOcs diff
That's kind of a lot, so let's unpack. go is an idiomatic term for a function helper (this could as easily be named f or frobnicator, it doesn't matter). It takes the character we're counting, which is split separately from the rest of its list, and calls it x. It runs a span (==x) against the rest of the list, which splits it into a tuple (longestPrefixThatMatches, rest). We return the length of that longest prefix (plus one, since we've stripped off the front character) paired with the character itself in a tuple, then cons that with the recursive case -- handing the rest of the list back to the outer function to handle.
What you want can be done by a one-liner
Prelude> import Data.List
Prelude Data.List> ls = ["a", "a", "b", "c", "c", "c", "d"]
Prelude Data.List> [(length x, head x) | x <- group ls]
[(2,"a"),(1,"b"),(3,"c"),(1,"d")]
I mix list comprehension with the group function. Basic concepts you can make yourselves familiar with.
contaOcs :: [String] -> [(Int, String)]
contaOcs xs = foldr foldContaOcs [] xs
where foldContaOcs s [] = (1, s):[]
foldContaOcs s ((n, ch):xs) = if ch == s then (n + 1, s) : xs
else (1, s): (n, ch): xs
I am very new to F# and have been looking at and running examples of simple problems I've found online. I stumbled on one that does not seem to work though and I was hoping someone could explain what is happening in this code and why. The functions should return the 1260 different options in lists, but instead it returns the empty list []
let rec group ns xs =
let rec combination n xs =
match n, xs with
| 0, xs -> [([], xs)]
| _, [] -> []
| n, x::xs ->
let ts = [for ys, zs in combination(n-1) xs do yield (x::ys, zs)]
let ds = [for ys, zs in combination n xs do yield (ys, x::zs)]
ts # ds
match ns, xs with
| [], _ -> ([])
| n::ns, xs ->
[for g, rs in combination n xs do
for gs in group ns xs do
yield g::gs]
[<EntryPoint>]
let main argv =
let list = ["One"; "Two"; "Three"; "Four"; "Five"; "Six"; "Seven"; "Eight"; "Nine"]
let groupSizes = [2;3;4]
printfn "%A" <| group groupSizes list
Looking at the second for it seems you're using a loop and recursion at the same time.
If you want to use recursion then you don't need to loop, recursion will loop for you, try changing the last lines to this:
| n::ns, xs ->
[for g, rs in combination n xs do
yield g
yield! group ns xs]
Here yield! is equivalent to the :: operation, I mean you can also write it like this:
[for g, rs in combination n xs do yield g] :: group ns xs
Note, that rsis not used, so you can write _ :
[for g, _ in combination n xs do yield g] :: group ns xs
Finally note you can use a map instead, with the function fst :
List.map fst (combination n xs do yield g) :: group ns xs
Gustavo's answers should fix your recursion, however it's unclear if you are trying to practice recursion, F#, or combinatorics. So in case you do many similar problems, even to double-check the output you could just use a combinatorics library in .NET. For example:
#r #"..\packages\Combinatorics.1.0.3.2\lib\net40\Combinatorics.dll"
open Combinatorics.Collections
let list = ResizeArray["One"; "Two"; "Three"; "Four"; "Five"; "Six"; "Seven"; "Eight"; "Nine"]
let groupSizes = [2;3;4]
groupSizes
|> Seq.collect (fun x -> Combinations<string>(list,x))
|> Seq.toList
//|> Seq.length
I made only one change, as the library expects Generic Collections, I used ResizeArray, which is just the usual C# List. Seq.collect will flatten the three collections into one, and at the end just use Seq.toList to manifest the result. The library also has Permutations and Variations, as well as an option to generate repetitions or not (seems that's the default).
How can I have multiple case statements which do not interleave with each other.
A toy example for instance:
fun multi_cases(xs) =
case xs of
[] => 5
| x::ys => case x of
1 => 2
|_ => 3
| x::[] => case x of
1 => 5
| _ => 7
;
stdIn:59.17-64.28 Error: types of rules don't agree [overload conflict]
earlier rule(s): [int ty] -> [int ty]
this rule: [int ty] list -> [int ty]
in rule:
:: (x,nil) =>
(case x
of 1 => 5
| _ => 7)
The last two case statements are getting mixed up how can I tell SML that they are indeed two independent case statements rather than a continuation/separate branch of case x of 1 => 2 ...
The patterns above as pointed in the answer below have an issue with their generality.
This code has two distinct problems:
As the question Nested case statements in SML that John links to says, case-ofs are a little tricky syntactically because their list of case statements never "stops". That is, your code actually gets parsed as:
fun multi_cases xs =
case xs of
[] => 5
| x::ys => case x of
1 => 2
| _ => 3
| x::[] => case x of
1 => 5
| _ => 7
which is nonsensical because that third pattern should have belonged to the outer case-of and not the inner (the inner case-of deals with x as an int, and the outer with x::[] as an int list).
Since your indentation does not actively help the compiler towards the intended meaning, using parentheses to "stop" the case-ofs from intertwining, like that post says, is the fix:
fun multi_cases xs =
case xs of
[] => 5
| x::ys => (case x of
1 => 2
| _ => 3)
| x::[] => (case x of
1 => 5
| _ => 7)
Alternatively you could turn the outer case-of into a match on the function's arguments itself and blend the inner case-of together with it, since a single pattern match allows for arbitrarily deep matching:
fun fun_cases [] = 5
| fun_cases [1] = 5
| fun_cases [_] = 7
| fun_cases (1::_) = 2
| fun_cases (_::_) = 3
Your two cases overlap because x::xs is a more general pattern than x::[]. That is, it also covers the list x::[] by setting xs to []. You could fix that in one of two ways:
List the least general pattern first, e.g.
case xs of
[] => 5
| [x] => ...
| x::_ => ...
Make that x::xs general pattern into a less general one by specifying that the list should have at least two elements:
case xs of
x :: _ :: _ => ...
| [x] => ...
| [] => ...
I have seen some similar questions, but nothing that really helped me. Basically the title says it all. Using SML I want to take a string that I have, and make a list containing each letter found in the string. Any help would be greatly appreciated.
One possibility is to use the basic logic of quicksort to sort the letters while removing duplicates at the same time. Something like:
fun distinctChars []:char list = []
| distinctChars (c::cs) =
let val smaller = List.filter (fn x => x < c) cs
val bigger = List.filter (fn x => x > c) cs
in distinctChars smaller # [c] # distinctChars bigger
end
If the < and > in the definitions of smaller and bigger were to be replaced by <= and >= then it would simply be an implementation of quicksort (although not the most efficient one since it makes two passes over cs when a suitably defined auxiliary function could split into smaller and bigger in just one pass). The strict inequalities have the effect of throwing away duplicates.
To get what you want from here, do something like explode the string into a list of chars, remove non-alphabetical characters from the resulting list, while simultaneously converting to lower case, then invoke the above function -- ideally first refined so that it uses a custom split function rather than List.filter twice.
On Edit: # is an expensive operator and probably results in the naïve SML quicksort not being all that quick. You can use the above idea of a modified sort, but one that modifies mergesort instead of quicksort:
fun split ls =
let fun split' [] (xs,ys) = (xs,ys)
| split' (a::[]) (xs, ys) = (a::xs,ys)
| split' (a::b::cs) (xs, ys) = split' cs (a::xs, b::ys)
in split' ls ([],[])
end
fun mergeDistinct ([], ys) = ys:char list
| mergeDistinct (xs, []) = xs
| mergeDistinct (x::xs, y::ys) =
if x < y then x::mergeDistinct(xs,y::ys)
else if x > y then y::mergeDistinct(x::xs,ys)
else mergeDistinct(x::xs, ys)
fun distinctChars [] = []
| distinctChars [c] = [c]
| distinctChars chars =
let val (xs,ys) = split chars
in mergeDistinct (distinctChars xs, distinctChars ys)
end
You can get a list of all the letters in a few different ways:
val letters = [#"a",#"b",#"c",#"d",#"e",#"f",#"g",#"h",#"i",#"j",#"k",#"l",#"m",#"n",#"o",#"p",#"q",#"r",#"s",#"t",#"u",#"v",#"w",#"x",#"y",#"z"]
val letters = explode "abcdefghijklmnopqrstuvwxyz"
val letters = List.tabulate (26, fn i => chr (i + ord #"a"))
Update: Looking at your question and John's answer, I might have misunderstood your intention. An efficient way to iterate over a string and gather some result (e.g. a set of characters) could be to write a "foldr for strings":
fun string_foldr f acc0 s =
let val len = size s
fun loop i acc = if i < len then loop (i+1) (f (String.sub (s, i), acc)) else acc
in loop 0 acc0 end
Given an implementation of sets with at least setEmpty and setInsert, one could then write:
val setLetters = string_foldr (fn (c, ls) => setInsert ls c) setEmpty "some sentence"
The simplest solution I can think of:
To get the distinct elements of a list:
Take the head
Remove that value from the tail and get the distinct elements of the result.
Put 1 and 2 together.
In code:
(* Return the distinct elements of a list *)
fun distinct [] = []
| distinct (x::xs) = x :: distinct (List.filter (fn c => x <> c) xs);
(* All the distinct letters, in lower case. *)
fun letters s = distinct (List.map Char.toLower (List.filter Char.isAlpha (explode s)));
(* Variation: "point-free" style *)
val letters' = distinct o (List.map Char.toLower) o (List.filter Char.isAlpha) o explode;
This is probably not the most efficient solution, but it's uncomplicated.