I started to learn Rust some time ago and I wonder if there is some way to write Rust code that is both concise and safe — in particular, avoiding `unwrap()`, casting functions and `try!()`.

Let's see an example. I wrote a software to generate random bookmarks and save them to a file, both in Rust and Haskell to compare.

First, I'll show you the Haskell version:

> 
> 
> ```
> import Control.Monad (liftM2, replicateM)
> import System.Environment (getArgs)
> import System.Random (newStdGen, randomRs)
> 
> main :: IO ()
> main = do
>     args <- getArgs
>     file <- generateFile args
>     case file of
>         Just (outputFile, fileContent) -> writeFile outputFile fileContent
>         Nothing -> putStrLn "Usage: ./GenBookmarks outputfile.html [count]"
> 
> generateFile :: [String] -> IO (Maybe (String, String))
> generateFile [outputFile, count] = do
>     fileContent <- generateFileContent $ read count
>     return $ Just (outputFile, fileContent)
> generateFile [outputFile] = generateFile [outputFile, "10"]
> generateFile _ = return Nothing
> 
> generateFileContent :: Int -> IO String
> generateFileContent count = do
>     bookmarks <- generateBookmarks count
>     let fileLines =
>             [ "<!DOCTYPE NETSCAPE-Bookmark-file-1>"
>             , "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">"
>             , "<TITLE>Bookmarks</TITLE>"
>             , "<H1>Menu des marque-pages</H1>"
>             , "<DL><p>"
>             ]
>             ++ bookmarks
>     return $ unlines fileLines
> 
> generateBookmarks :: Int -> IO [String]
> generateBookmarks count =
>     liftM2 (++) (replicateM count generateDirectory) (replicateM (count * 4) generateBookmark)
>     where generateDirectory = do
>                 directoryName <- generateName
>                 return $ "<DT><H3 ADD_DATE=\"1438910135\" LAST_MODIFIED=\"1438910135\">" ++ directoryName ++ "</H3>"
>           generateBookmark = do
>                 bookmarkName <- generateName
>                 return $ "<DL><p>\n<DT><A HREF=\"https://" ++ bookmarkName ++ ".com/\">" ++ bookmarkName ++ "</a>\n</DL><p>"
> 
> generateName :: IO String
> generateName = do
>     g <- newStdGen
>     return $ take 10 $ randomRs ('a', 'z') g
> 
> ```
> 
> 

Here is the Rust version:

```
extern crate rand;

use std::env;
use std::fs::File;
use std::io::Write;

use rand::Rng;

fn options() -> Option<(String, i32)> {
    match env::args().count() {
        2 => Some ((env::args().nth(1).unwrap(), 10)),
        3 => Some (
            (
                env::args().nth(1).unwrap(),
                env::args().nth(2).unwrap().parse().unwrap(),
            )
        ),
        _ => None,
    }
}

fn generate_name() -> String {
    rand::thread_rng().gen_ascii_chars().take(10).collect()
}

fn write_data(file: &mut File, count: i32) -> Result<(), std::io::Error> {
    for _ in 1..count {
        let directory_name = generate_name();
        let directory = "<DT><H3 ADD_DATE=\"1438910135\" LAST_MODIFIED=\"1438910135\">".to_string() + &directory_name + "</H3>";
        try!(file.write(directory.as_bytes()));
        try!(file.write(b"\n"));
    }
    for _ in 1..count * 4 {
        let bookmark_name = generate_name();
        let bookmark = "<DL><p>\n<DT><A HREF=\"https://".to_string() + &bookmark_name + ".com/\">" + &bookmark_name + "</a>\n</DL><p>";
        try!(file.write(bookmark.as_bytes()));
        try!(file.write(b"\n"));
    }
    Ok(())
}

fn generate_file(outputfile: String, count: i32) -> Result<(), std::io::Error> {
    let data = vec![
        "<!DOCTYPE NETSCAPE-Bookmark-file-1>",
        "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">",
        "<TITLE>Bookmarks</TITLE>",
        "<H1>Menu des marque-pages</H1>",
        "<DL><p>",
    ];
    let mut file = try!(File::create(outputfile));
    for line in data {
        try!(file.write(line.as_bytes()));
        try!(file.write(b"\n"));
    }
    try!(write_data(&mut file, count));
    Ok(())
}

fn main() {
    match options() {
        Some ((outputfile, count)) => {
            match generate_file(outputfile, count) {
                Ok(()) => (),
                Err(error) => println!("{}", error),
            }
        },
        None => println!("Usage: ./GenBookmarks outputfile.html [count]"),
    }
}

```

There is some parts of the Rust code that I feel are not good.
The `options()` function looks really bad and unsafe (and it is unsafe for parsing the number). The Haskell version use pattern matching on the program arguments (and is unsafe on parsing the number too, but this is not the point), but I didn't find a way to do something similar in Rust. In Rust, pattern matching against an array is unsafe by now.

Moreover, all the file writing (with all these `try!`) looks bad. Is there a better way of doing this?

Finally, having to use `to_string()`, `as_bytes()` and `b"some text"` is cumbersome. Is it possible to avoid that?