SML Convert integer to list - sml

The below code is able to successfully convert an integer file to a list however i need to convert an integer to a list such as. Can anyone assist please ?
readint 134516;
result should be a list [1,3,4,5,1,6];
fun readint(infile : string) =
let
val ins = TextIO.openIn infile
fun loop ins =
case TextIO.scanStream (Int.scan StringCvt.DEC) ins of
SOME int => int :: loop ins
| NONE => []
in
loop ins before TextIO.closeIn ins
end;

You want to to create a recursive function that uses the modulo (mod) and integer division (div) operators.

Related

Ask user for list input in Haskell

I found this code online, but it's not running.
main = do
xs <- getLine []
print xs
So how do I ask the user for list input in Haskell? I am new to Haskell, please explain when you answer. Thanks.
You do it e.g. like this:
main :: IO ()
main = do
xs <- getLine
let { ints :: [Int]
; ints = read xs
}
print $ take 2 ints
and you must type in the input in a valid list syntax, e.g.
[1,2,3]
Do take note, each line in a do-block must start at the same indentation level (unless explicit separators { ; } are used).
getLine is an IO action that produces a string, nothing else. You need to process that string once you receive it. As an example, here's an IO action that will parse an appropriate input into a list of Int values.
getIntList :: IO [Int]
getIntList = fmap read getLine
main = do
ints <- getIntList
print ints
There is a Read instance for lists, so the following works:
> read "[1,2,3]" :: [Int]
[1,2,3]
getIntList uses the Functor instance for IO to apply read to the string that getLine will produce; read's concrete type will be inferred from the type given to getIntList: since getIntList :: IO [Int], then fmap read :: IO String -> IO [Int], and so read :: String -> [Int] will be used.

How can I concatenate user input in a list

I would like to get codes from the user and insert it in a list, but the problem is when the user say that don't wanna insert more codes. I don't saved a list with the numbers because I'm using recursion to call the method again, so when I should return the list I don't have it.
insertCode :: [Integer]
insertCode = do
putStrLn "Code:"
code <- getLine
putStrLn "Another? (Y/N)"
if(resp == "Y" || resp == "y") then (read code::String->Integer):insertCode else --I don't know
I'm sorry for my stupids questions, I imagine that is obvious but I have a problem with functional programming
First of all, your type signature is wrong. insertCode uses the IO monad, so the type must be IO [Integer]. You are also missing the conversion of code from a String to an Integer (I use readLn to accomplish that; you were trying to convert code into a function, not an Integer) and you are missing a getLine to get the Y/N response from the user.
Once that is fixed, you might write something like the following:
insertCode :: IO [Integer]
insertCode = do
putStrLn "Code:"
code <- readLn
putStrLn "Another? (Y/N)"
response <- getLine
result <- if (response == "Y" || response == "y")
then insertCode
else return []
return (code : result)
This is a little verbose, but tries to be explicit about how the monad is used. Whether the user enters Y or N, code must be appended to a list extracted from a monad: either a list extracted from a recursive use of insertCode, or an explicit empty list.

SML - Iterate through String

I'm trying to find if sentences read from a file has some pattern.
So far, I've written the code that reads all the sentences from file line by line, and puts those sentences to an array.
val infile = "c:/input.txt" ;
fun readlist (infile : string) =
let val ins = TextIO.openIn infile
fun loop ins = case TextIO.inputLine ins of
SOME line => line :: loop ins
| NONE => []
in loop ins before TextIO.closeIn ins
end;
val pureGraph = readlist(infile);
Try to write a function that evaluates to true if the letter a is in a string. Use explode to get a list of Chars. Recurse or fold over that list until you find a or reach the end. When you have that function, generalize it to any character. This will probably lead you to an O(n^2) runtime complexity.
Another approach is to sort the character list, remove duplicates, zip it with the correct list of characters and compare each tuple with recursion/fold. This should run in O(n log n) time because of the sort.
A third approach is to fold over the character list with an array or a hash map. In the array or map you add in what the current character is. At the end you see if all characters were found. This approach should run in O(n) time if your hashmap is constant-time.
Divide and conquer your problem:
Write a function isPanagram : string -> bool that determines this for a single line.
One strategy could be: Start with the set of all letters. Loop through the string, and for each character in the string, remove it from the set until the end of the string, or the set is empty. If the set is empty, it is a panagram. This requires that you represent sets in some way, e.g. with a list or a binary search tree.
Consider looping through the string by index, rather than exploding it:
val allLetters = ...
fun remove x ... = ...
fun isEmpty ... = ...
fun isPanagram s =
let val len = size s
fun loop i missingLetters =
isEmpty missingLetters orelse
i < len andalso loop (i+1) (remove (String.sub (s, i)) missingLetters)
in loop 0 allLetters end
Write a function readLines : string -> string list that reads the content of a file and separates the lines into elements of a list:
fun isLinebreak c = c = #"\r" orelse c = #"\n"
fun readLines filename =
let val ins = TextIO.openIn filename
val data = TextIO.inputAll ins
val _ = TextIO.closeIn ins
in String.tokens isLinebreak data end
(Yes, reading the file one line at a time will save memory.)
The SML/NJ library has a number of data structures which can be used for things like sets and hash tables. They are not exactly well-documented, but this explains a bit how to use them. Using their set library, you can write something like this:
structure CharSet = RedBlackSetFn(struct
type ord_key = char
val compare = Char.compare
end)
val alphabet = CharSet.fromList (explode "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
fun isPanagram s =
let val chars = CharSet.fromList (map Char.toUpper (explode s))
val letters = CharSet.intersection (chars,alphabet)
in CharSet.numItems letters = 26
end;
used like this:
- isPanagram "We promptly judged antique ivory buckles for the next prize.";
val it = true : bool
- isPanagram "We promptly judged antique plastic buckles for the next prize.";
val it = false : bool

The usage of before in ML

ML's before is described in http://sml-family.org/Basis/general.html as
a before b
returns a. It provides a notational shorthand for evaluating a, then b, before
returning the value of a.
When I tried to use this command expecting x = 4 and (4+1) is evaluated
val x = (3+1 before 4+1)
I have the error message:
Standard ML of New Jersey v110.78 [built: Sun Apr 26 01:06:11 2015]
- stdIn:1.11-1.25 Error: operator and operand don't agree [overload conflict]
operator domain: [+ ty] * unit
operand: [+ ty] * [+ ty]
in expression:
(3 + 1 before 4 + 1)
-
What might be wrong?
Edit
From Matt's answer, I should have used
val x = (3+1 before print "<end>")
I also found that before is used to close the stream after processing some FileIO functions.
(* http://stackoverflow.com/questions/2168029/open-file-in-mlsmlnj *)
val infile = "input.txt" ;
(* reading from file follow this to list of string per line *)
fun readlist (infile : string) = let
val ins = TextIO.openIn infile
fun loop ins =
case TextIO.inputLine ins of
SOME line => line :: loop ins
| NONE => []
in
loop ins before TextIO.closeIn ins
end ;
val pureGraph = readlist(infile);
size (hd pureGraph)
From here, it says that the type of before is before : ('a * unit) -> 'a, and as your type error specifies, it is expecting the type of the second argument to be of type unit, however, you have supplied something of type int. Try doing val x = (3+1 before ()) and you should get the expected result. The intended purpose is to have the second argument be some sort of side affecting computation, such as manipulating a ref cell or doing some IO, which you want to run prior to evaluating your first argument. It seems that the following are the same:
val x = e1 before e2
and
val x = let val a = e1
val _ = e2
in a end
That said, before is not something I really use , so if anyone else has anything to add, comments are certainly welcome.

Haskell product of list

So I need to write a program returning the product of a list of integers.Here is what I tried to make.But every time I get "parse error"on the = sign of the 4th line.
--product.hs
product :: [Integer] -> Integer
product [] = 1
product i f = foldl (*) 1 [i..f]
main = do
print "Please enter first number"
i <- readLn
print "Please enter second number"
f <- readLn
print "The result is:"
print (product i f)
I also tried with
product (x:xs) = x * product xs
but it still gives me parse error on the = sign
In the following code
product :: [Integer] -> Integer
product [] = 1
product i f = foldl (*) 1 [i..f]
you declare the type of product is [Integer] -> Integer, but in the second clause, you give it two parameters, this obviously does not match with its type.
You can define it simply like this
product xs = foldl (*) 1 xs
and use it like this
product [i..f]
By the way, product is a standard function offered by Prelude, with a similar (better) type and the same function.
Your parse error is probably due to inconsistent indentation. A good advice is to only use spaces for indentation. While it is possible to use tabs, it is easy to trip up with an editor that doesn't treat tabs precisely the way Haskell does.
Here, all your function declarations need to be aligned vertically, as do all the statements in your do block.