Jason Deol, Aiden Patel, Evgeniy (Eugene) Tchistiakov
What is the problem?
It's difficult to keep track of an ever-increasing number of passwords for various websites and accounts. Our program will take a master password from the user, which will decrypt an encrypted file full of accounts with associated usernames and password for easy access.
What is the something extra?
Our extra addition to the basic program will be a password generator to recommend strong passwords for users.
What did we learn from doing this?
The most difficult part of our project was the encryption and decryption of user information, as well as working with JSON files which is always complicated. Since the program often creates and edits account information, we created a new data type 'Entry', so we learned a lot about using constructors to access and edit data in this new type. Additionally, with all the user interaction we had to develop a solid grasp of IO types, lots of do-blocks and how to resolve conflicts of that nature (such as expected type: IO [Entry] vs actual type: IO String, which came up plenty of times). Above all, we learned the value of external packages available from other users, and specifically how valuable an abstracted dependency can be, in that it can be applied to many different problems using the same code structure.
In terms of how effective functional programming is for this password manager, it seems that do-blocks are quite effective at simplifying user interfaces (with sufficient understanding of handling IO types). For example, our primary user-interface function 'mainScreen' is essentially a long sequence of do-blocks, which works well and is easy to follow. However, a sequence of imperative commands would be just as effective as a do-block in the case of a password manager. We conclude that functional programming is perfectly usable for this type of program, but it doesn't provide a distinct advantage over imperative programming.