How to read pair by pair from a file in SML? - functional-programming

I want to read N pairs from a file and store them as a tuples in a list.For example if i have these 3 pairs : 1-2 , 7-3, 2-9 i want my list to look like this -> [(1,2),(7,3),(2-9)]
I tried something like this:
fun ex filename =
let
fun readInt input = Option.valOf (TextIO.scanStream (Int.scan StringCvt.DEC) input)
val instream = TextIO.openIn filename
val T = readInt instream (*number of pairs*)
val _ = TextIO.inputLine instream
fun read_ints2 (x,acc) =
if x = 0 then acc
else read_ints2(x-1,(readInt instream,readInt instream)::acc)
in
...
end
When i run it i get an exeption error :/ What's wrong??

I came up with this solution. I reads a single line from the given file. In processing the text it strips away anything not a digit creating a single flat list of chars. Then it splits the flat list of chars into a list of pairs and in the process converts the chars to ints. I'm sure it could be improved.
fun readIntPairs file =
let val is = TextIO.openIn file
in
case (TextIO.inputLine is)
of NONE => ""
| SOME line => line
end
fun parseIntPairs data =
let val cs = (List.filter Char.isDigit) (explode data)
fun toInt c =
case Int.fromString (str c)
of NONE => 0
| SOME i => i
fun part [] = []
| part [x] = []
| part (x::y::zs) = (toInt x,toInt y)::part(zs)
in
part cs
end
parseIntPairs (readIntPairs "pairs.txt");

Related

F# (F sharp) unzip function explained

I'm taking a university course in functional programming, using F#, and I keep getting confused about the logical flow of the following program. Would anyone care to explain?
let rec unzip = function
| [] -> ([],[])
| (x,y)::rest ->
let (xs,ys) = unzip rest
(x::xs,y:ys);;
So this program is supposed to take a list of pairs, and output a pair of lists.
[(1,'a');(2,'b')] -> ([1;2],['a','b'])
It seems to me, like the base case where the argument (list) is empty, the format of the output is given, but I don't understand how the third and fourth line is evaluated.
let (xs,ys) = unzip rest
(x::xs,y:ys);;
Firstly, this is a recursive function - the rec keyword is a giveawy :).
These can be quite hard to get you head around, but are quite common in functional programming.
I'll assume you are OK with most of the pattern matching going on, and that you are aware of the function keyword shorthand.
let rec unzip = function
| [] -> ([],[])
| (x,y)::rest ->
let (xs,ys) = unzip rest
(x::xs,y:ys);;
You seem quite happy with:
| [] -> ([],[])
Given an empty list, return a tuple with 2 empty lists. This isn't just a guard clause, it will be used later to stop the recursive program running forever.
The next bit...
| (x,y)::rest ->
Takes the first element (head) of the list and splits it off from the tail. It also deconstructs the head element which is a tuple into 2 values x and y.
The could be written out long hand as:
| head::rest ->
let x,y = head
Now is the fun part where it calls itself:
let (xs,ys) = unzip rest
(x::xs,y:ys);;
It might help to walk though an example an look at what goes on at each step:
unzip [(1,'a');(2,'b');(3,'c')]
x = 1
y = 'a'
rest = [(2,'b'); (3,'c')]
unzip rest
x = 2
y = 'b'
rest = [(3,'c')]
unzip rest
x = 3
y = 'c'
rest = []
unzip rest
return [],[]
xs = []
ys = []
return [x:xs],[y:ys] # 3:[] = [3], 'c':[] = ['c']
xs = [3]
ys = ['b']
return [x:xs],[y:ys] # 2:[3] = [2,3], 'b':['c'] = ['b', 'c']
xs = [2,3]
ys = ['b','c']
return [x:xs],[y:ys] # 1:[2;3] = [1,2,3], ['a']:['b';'c'] = ['a', 'b', 'c']
done

Extracting the name of a variable

How can we build a function in F# that outputs the name of the variable passed in? For example:
let someVar1 = "x"
getVarname someVar1 //output would be "someVar1"
let someVar2 = "y"
getVarname someVar2 //output would be "someVar2"
let f toString = fun a -> printfn "%s: %d" (toString a) a
let x = 1
f getVarname x //output would be: "x: 1"
I found a similar question in C# here (get name of a variable or parameter), but I was unable to make it work in F#.
If you use quotations and static methods, you can already capture the name of the variable in F# 4 using the ReflectedDefinition attribute. The Demo.GetVarName static method in the following example returns the name of the variable used as an argument together with the value:
open Microsoft.FSharp.Quotations
type Demo =
static member GetVarName([<ReflectedDefinition(true)>] x:Expr<int>) =
match x with
| Patterns.WithValue(_, _, Patterns.ValueWithName(value, _, name)) ->
name, value :?> int
| _ -> failwithf "Argument was not a variable: %A" x
let test ()=
let yadda = 123
Demo.GetVarName(yadda)
test()
This works for local variables as in the test() function above. For top-level variables (which are actually compiled as properties) you also need to add a case for PropertyGet:
match x with
| Patterns.WithValue(_, _, Patterns.ValueWithName(value, _, name)) ->
name, value :?> int
| Patterns.WithValue(value, _, Patterns.PropertyGet(_, pi, _)) ->
pi.Name, value :?> int
| _ -> failwithf "Argument was not a variable: %A" x
The nameof implementation has the operator in F# core, but the F# 5 compiler bits haven't shipped yet.
When it does, you can use it to get the name of a symbol.
let someVar1 = None
let name = nameof someVar1 // name = "someVar1"
For now, we can maybe abuse the dynamic operator to get us a shim which you can eventually replace with nameof
let name = ()
let (?) _ name = string name
Usage:
let someVar1 = None
let name = name?someVar1
It doesn't read too bad, and you get some degree of auto-completion.
If you really want to be able to retrieve the local name and value at the call-site, there's quotations.
let printVar = function
| ValueWithName(value, _type, name) -> printfn "%s = %A" name value
| _ -> ()
The usage is a bit noisy, though.
let someVar1 = 12
printVar <# someVar1 #> //prints someVar1 = 12

How do I print out year with average number recursively in F#?

Okay, so I have approached this headache for a couple days by trying to figure out how to print out year with average number from per line in my text file. I asked this similar question a couple days ago so basically I'm asking the same question, How do I print out lines recursively from a text file along with the average value of total elements from per line?
this goes on. However, I have created several functions. Now, here is my new question. Why does my program's output looks like this in the picture below? I have commented out a couple questions in my codes. I have been expecting to have output like
2010: 3.5788888
2009: 4.697858
This list goes on recursively.
here is my updated codes:
let ReadFile filename =
[ for line in System.IO.File.ReadLines(filename) -> line ]
let ParseLine (line:string) =
let strings = line.Split('\t')
let strlist = Array.toList(strings)
let year = System.Int32.Parse(strlist.Head)
let values = List.map System.Double.Parse strlist.Tail
(year, values)
let rec print (year, values) =
if values = [] then
()
else
printfn "%A: %A" year values.Head
print (year, values.Tail)
let avg (values:double list) = //this function can compute the average, but it wont work when I do in main, print(firstYear, avg (firstYear1))
let rec sum values accum =
match values with
| [] -> accum
| head :: tail -> sum tail (accum + head/12.0)
sum values 0.0
let rec sum (year, values:double list) =
if values = [] then
0.0
else
values.Head + sum (year, values.Tail)
[<EntryPoint>]
let main argv =
// read entire file as list of strings:
let file = ReadFile "rainfall-midway.txt"
printfn "** Rainfall Analysis Program **"
printfn ""
// let's parse first line into tuple (year, list of rainfall values),
// and then print for debugging:
let (year, values) = ParseLine file.Head
let firstYear = file.Head
let firstYear1 = file.Tail
//let data = List.map ParseLine file //I know map would be the key, but how does this work with year and its elements?
//let firstYear = data.Head
//let firstYear = data.Head
//print firstYear
print (firstYear, firstYear1)
//let S = sum firstYear
//printfn "%A" S
//let A = S / 12.0
//printfn "%A" A
// done:
printfn ""
printfn ""
0 // return 0 => success
The code you have is actually quite close to giving you the data you expect. There are a couple changes you could make to simplify things.
First to answer your question
Why does my program's output looks like this in the picture below?
This is because you are printing out the year and all of the parsed values (this doesn't match the code which just prints out the file). An easy way to resolve this is to have the ParseLine function calculate the average. You will need to move the avg prior to the ParseLine function but that should not be a problem.
let avg (values:double list) =
let rec sum values accum =
match values with
| [] -> accum
| head :: tail -> sum tail (accum + head/12.0)
sum values 0.0
let ReadFile filename =
[ for line in System.IO.File.ReadLines(filename) -> line ]
let ParseLine (line:string) =
let strings = line.Split('\t')
let strlist = Array.toList(strings)
let year = System.Int32.Parse(strlist.Head)
let values = List.map System.Double.Parse strlist.Tail
(year, avg values) // calculate avg here
Once that is done, you can use a map to run ParseLine on all lines from the file.
let result = file |> List.map ParseLine
Then to print out the results you need only iterate through the result list.
result |> List.iter(fun (year, avgRainfall) -> printfn "%i: %f" year avgRainfall)
That said we could just remove the sum and avg functions altogether and use fold instead in our ParseLine function.
let ParseLine (line:string) =
let strings = line.Split('\t')
let strlist = Array.toList(strings)
let year = System.Int32.Parse(strlist.Head)
year, (strlist.Tail |> List.fold(fun state el -> (System.Double.Parse el + state)) 0.0) / float strlist.Tail.Length
If you don't want to change the ParseLine function then you can do the following:
let result = file |> List.map(fun el ->
let (year, values) = ParseLine el
(year, avg values))

F#- AsyncSeq - how to return values in a list

Attempting to find anagrams in a list of words using F Sharps Async Sequences (I am aware there are better algorithms for anagram finding but trying to understand Async Sequneces)
From the 'runTest' below how can I
1. async read the collecion returned and output to screen
2. block until all results return & display final count/collection
open System
open System.ServiceModel
open System.Collections.Generic
open Microsoft.FSharp.Linq
open FSharp.Control
[<Literal>]
let testWord = "table"
let testWords = new List<string>()
testWords.Add("bleat")
testWords.Add("blate")
testWords.Add("junk")
let hasWord (word:string) =
let mutable res = true
let a = testWord.ToCharArray() |> Set.ofArray
let b = word.ToCharArray() |> Set.ofArray
let difference = Set.intersect a b
match difference.Count with
| 0 -> false
| _ -> true
let test2 (words:List<string>, (word:string)) : AsyncSeq<string> =
asyncSeq {
let res =
(words)
|> Seq.filter(fun x-> (hasWord(x)) )
|> AsyncSeq.ofSeq
yield! res
}
let runTest = test2(testWords,testWord)
|> //pull stuff from stream
|> // output to screen
|> ignore
()
So as you have the test2 function returning an asyncSeq. Your questions:
1. async read the collecion returned and output to screen
If you want to have some side-effecting code (such as outputting to the screen) you can use AsyncSeq.iter to apply a function to each item as it becomes available. Iter returns an Async<unit> so you can then "kick it off" using an appropriate Async method (blocking/non-blocking).
For example:
let processItem i =
// Do whatever side effecting code you want to do with an item
printfn "Item is '%s'" i
let runTestQ1 =
test2 (testWords, testWord)
|> AsyncSeq.iter processItem
|> Async.RunSynchronously
2. block until all results return & display final count/collection
If you want all the results collected so that you can work on them together, then you can convert the AsyncSeq into a normal Seq using AsyncSeq.toBlockingSeq and then convert it to a list to force the Seq to evaluate.
For example:
let runTestQ2 =
let allResults =
test2 (testWords, testWord)
|> AsyncSeq.toBlockingSeq
|> Seq.toList
// Do whatever you would like with your list of results
printfn "Final list is '%A' with a count of %i" allResults (allResults.Length)

functional programming with less recursion?

I am currently doing reasonably well in functional programming using F#. I tend, however, to do a lot of programming using recursion, when it seems that there are better idioms in the F#/functional programming community. So in the spirit of learning, is there a better/more idiomatic way of writing the function below without recursion?
let rec convert line =
if line.[0..1] = " " then
match convert line.[2..] with
| (i, subline) -> (i+1, subline)
else
(0, line)
with results such as:
> convert "asdf";;
val it : int * string = (0, "asdf")
> convert " asdf";;
val it : int * string = (1, "asdf")
> convert " asdf";;
val it : int * string = (3, "asdf")
Recursion is the basic mechanism for writing loops in functional languages, so if you need to iterate over characters (as you do in your sample), then recursion is what you need.
If you want to improve your code, then you should probably avoid using line.[2..] because that is going to be inefficient (strings are not designed for this kind of processing). It is better to convert the string to a list and then process it:
let convert (line:string) =
let rec loop acc line =
match line with
| ' '::' '::rest -> loop (acc + 1) rest
| _ -> (acc, line)
loop 0 (List.ofSeq line)
You can use various functions from the standard library to implement this in a more shorter way, but they are usually recursive too (you just do not see the recursion!), so I think using functions like Seq.unfold and Seq.fold is still recursive (and it looks way more complex than your code).
A more concise approach using standard libraries is to use the TrimLeft method (see comments), or using standard F# library functions, do something like this:
let convert (line:string) =
// Count the number of spaces at the beginning
let spaces = line |> Seq.takeWhile (fun c -> c = ' ') |> Seq.length
// Divide by two - we want to count & skip two-spaces only
let count = spaces / 2
// Get substring starting after all removed two-spaces
count, line.[(count * 2) ..]
EDIT Regarding the performance of string vs. list processing, the problem is that slicing allocates a new string (because that is how strings are represented on the .NET platform), while slicing a list just changes a reference. Here is a simple test:
let rec countList n s =
match s with
| x::xs -> countList (n + 1) xs
| _ -> n
let rec countString n (s:string) =
if s.Length = 0 then n
else countString (n + 1) (s.[1 ..])
let l = [ for i in 1 .. 10000 -> 'x' ]
let s = new System.String('x', 10000)
#time
for i in 0 .. 100 do countList 0 l |> ignore // 0.002 sec (on my machine)
for i in 0 .. 100 do countString 0 s |> ignore // 5.720 sec (on my machine)
Because you traverse the string in a non-uniform way, a recursive solution is much more suitable in this example. I would rewrite your tail-recursive solution for readability as follows:
let convert (line: string) =
let rec loop i line =
match line.[0..1] with
| " " -> loop (i+1) line.[2..]
| _ -> i, line
loop 0 line
Since you asked, here is a (bizarre) non-recursive solution :).
let convert (line: string) =
(0, line) |> Seq.unfold (fun (i, line) ->
let subline = line.[2..]
match line.[0..1] with
| " " -> Some((i+1, subline), (i+1, subline))
| _ -> None)
|> Seq.fold (fun _ x -> x) (0, line)
Using tail recursion, it can be written as
let rec convert_ acc line =
if line.[0..1] <> " " then
(acc, line)
else
convert_ (acc + 1) line.[2..]
let convert = convert_ 0
still looking for a non-recursive answer, though.
Here's a faster way to write your function -- it checks the characters explicitly instead of using string slicing (which, as Tomas said, is slow); it's also tail-recursive. Finally, it uses a StringBuilder to create the "filtered" string, which will provide better performance once your input string reaches a decent length (though it'd be a bit slower for very small strings due to the overhead of creating the StringBuilder).
let convert' str =
let strLen = String.length str
let sb = System.Text.StringBuilder strLen
let rec convertRec (count, idx) =
match strLen - idx with
| 0 ->
count, sb.ToString ()
| 1 ->
// Append the last character in the string to the StringBuilder.
sb.Append str.[idx] |> ignore
convertRec (count, idx + 1)
| _ ->
if str.[idx] = ' ' && str.[idx + 1] = ' ' then
convertRec (count + 1, idx + 2)
else
sb.Append str.[idx] |> ignore
convertRec (count, idx + 1)
// Call the internal, recursive implementation.
convertRec (0, 0)

Resources