how to display only the title from the tuple in haskell? - list

I have the following code which creates the database...
type Title = String
type Singer = [String]
type Year = Int
type Fan = String
type Fans = [Fan]
type Film = (Title, Actor, Year, Fans)
type Database = [Film]
filmDatabase :: Database
filmDatabase = [("Wrapped up", ["Olly Murs"], 2014, ["Garry", "Dave", "Zoe", "Kevin", "Emma"]),
("Someone Like you", ["Adele"], 2011, ["Bill", "Jo", "Garry", "Kevin", "Olga", "Liz"]),
I then have used the following code to search for A fan and display all the music they like.
fanOfFilms :: Fan -> Film -> Bool
fanOfFilms fan (t, _, _, f)
|elem fan f = True
|otherwise = False
givenUser :: Fan ->[Film]
givenUser fan = filter (fanOfFilms fan) testDatabase
I want to now take this code and make it only display the titles. How do i do this? I have tried using map and tried to use pattern matching but cannot get it to work?!
code I tried
titleOnly :: (t, a, y, f) -> (t, f)
titleOnly (t, _, _, f) = (t, f)`
I then tried linking this to FansFilms but it looks messy and i don't know how to correctly

You can create a function that, given a Film, returns its title:
filmTitle :: Film -> Title
filmTitle (t, _, _, _) = t
And then map this function over the list of Films returned by givenUser.
givenUserTitles :: Fan -> [Title]
givenUserTitles fan = map filmTitle (givenUser fan)

To get the first item in a tuple, use fst. You can get the second item with snd, which is useful because many times you will use ordered pairs as tuples. The most readable way to get the title out of the tuple I think would be:
title :: Film -> Title
title (t,_,_,_) = t
To get the fans,
fans :: Film -> Fans
fans (_,_,_,f) = f
Now what you want to do is match up a fan with all of the titles they are a fan of, correct? This means that you will need to check each film title if the fan is a member of the list of fans. You can do this with the elem function.
Let me know if any of this does or doesn't work!

Using the lens package (not that I'm saying that you should use it), you can use _1, _2 etc ...
Example
("title", "actor", "year", "fans") ^. _4
>>> "fan".
However, in that situtation, you probably should use a record.

Related

F# Nested lists immutability

I am trying to pick F# again and I have a case where I find it very difficult to deal with immutability.
In most cases I find immutability very nice. However, I find it very hard to deal with nested collections.
I would like to write a single user GUI program.
For simplicity let’s say we have the model:
type Employee =
{
Name : string
}
type Company =
{
Name : string
Employees : Employee list
}
If I modify an existing Employee with
let myNewEmployee = { myEmployee with Name = "John Smith" }
I get a new Employee and that is fine. However, here comes the chain of problems:
I need to remove the old myEmployee and add myNewEmployee to the
Company’s Employees list.
That provokes a mutation in the list with yields a new list.
That forces me to create a new Company record in order to inject the new collection, having to rebuild entire Company list I have.
In other words, changing an employee’s name, makes me rebuild the entire data structure.
Every time I am stumped, I have found that F# has a different and creative way of doing things.
I assume that it is my ignorance on not knowing how to deal with this situation in a functional way, please enlighten me ;)
Should I be using other F# libraries, like F# Data ?
TIA,
David
I think the answer depends partly on the larger context - such as how is the user interface of your application implemented. You are right that modifying one name in a company requires you to produce a new list and a new company record. That is not too bad if you do it in a single call to List.map though.
To make the sample easier, I added ID of type int to each emplyee:
let updateName id name company =
let newEmployees = company.Employees |> List.map (fun emp ->
if emp.ID = id then { emp with Name = name } else emp)
{ company with Employees = newEmployees }
If you are using something like the Elm architecture, then this is probably a reasonable way to go.
In some cases, you can do a more clever thing (but it depends on your scenario). For example, you could create a new type to represent a company with a list of updates that have been applied to it:
type Update =
| Rename of id:int * newName:string
type UpdatedCompany =
{ Company : Company
Updates : Update list }
Now changing a name is just a matter of appending a new Rename update to the list of Updates. Of course, once you need to display the final Company, you will need to iterate over all the employees (as above) and apply the updates. However, if you do a lot of updates before you need to get a new final Company value, this might be a nice trick.
The functional-first F# style means that you keep your functions pure by default i the core of your program and moving the necessary side-effects towards the edge of your program.
I need to remove the old myEmployee and add myNewEmployee to the Company’s Employees list.
Do you really need to do this? I encourage you to think about this chain going in the opposite direction. Why do you need this new list? What effect does that ultimately have on the outside world? Maybe the complete list can be built up in one pass by restructuring your code to a functional style. Maybe you are responding to user input and it's fine to build a new list every time. Maybe it would be better to use a different data structure like a Map (immutable dictionary) with the employee ID as the key.
Long entry with no clear answers but some ideas on how to deal with nested immutable data
As the OP noted, when discussing immutability an area that is ignored how to update nested properties. While this is trivial in mutable structure (just navigate there and update the property) with immutable structures one need to navigate there, create a copy with the updated property and then recreate all parents.
Luckily people have been thinking about this already and the functional pattern to address this is called Lenses or Prisms.
Lenses have a reputation of being somewhat difficult.
But that IMO is because in Haskell they talk about polymorphic lenses which can be defined like this:
type Lens s t a b = forall f. Functor f => (a -> f b) -> (s -> f t) // Que?
Braver souls than me have implemented polymorphic lenses in F# (which has a more simplistic type system than Haskell): http://www.fssnip.net/7Pk
(The polymorphic lens implementation in F# is provided AFAIK by the guy behind Hopac. He's pretty decent I say)
Polymorphic lenses are cool but if you remove the polymorphic bit lenses become much simpler to understand and still very usable.
Basically a lens is a pair of a getter and a setter function. It could look like this in F#:
type Lens<'T, 'U> = ('T -> 'U)*('T -> 'U -> 'T)
Given a value the getter get a property of that value. Given a value and property value the setter creates a new copy of the value with the property updated.
It can be thought of as a functional composable properties remotely comparable to .NET properties.
Given that your example (and many real-world things) deals with maps and lists Prisms are typically more usable. Here is one proposal:
type [<Struct>] Prism<'T, 'U> = Prism of ('T -> 'U option)*('T -> 'U -> 'T)
The only difference here is that the getter might return None if the property don't exists, for example if the employee don't exist in the list.
For a prism we define the operator >-> which combines a two prisms into a new one that let's you get the focused property as well as updating it like so:
let p = PropertyA >-> PropertyB >-> Property C
// Updates the nested property c in b in a and returns a new instance
let newA = a |> set p c
Let's see how this could look for the example in OPs post.
type Company =
{
Name : string
Employees : Map<EmployeeNo, Employee>
}
// Define Prisms for properties of Company
static member _Name : Prism<Company, _> = prism' (fun t v -> { t with Name = v }) (fun t -> t.Name |> Some)
static member _Employees : Prism<Company, _> = prism' (fun t v -> { t with Employees = v }) (fun t -> t.Employees |> Some)
Unfortunately there is a bit of boiler-plate code surrounding prisms, but that can be mitigated with code-gen tools and possibly even type-providers.
We define Employee in a similar manner and we can start defining functions that allows us manipulating the nested immutable structure.
// Uses Prisms to update the email
let updateEmail company employeeNo newEmail =
company
// The path to the Employee email
|> set (Company._Employees >-> lookup employeeNo >-> Employee._Email) newEmail
Prisms are chainable useful when updating more than one property.
// Uses Prisms to update the position and salary
let updatePosition company employeeNo newPosition newSalary =
company
// The path to the Employee position
|> set (Company._Employees >-> lookup employeeNo >-> Employee._Position) newPosition
// The path to the Employee salary
|> set (Company._Employees >-> lookup employeeNo >-> Employee._Salary ) newSalary
While the example above works it's inefficient to construct two Company objects and throw away the first. Better would be to navigate to the correct Employee and update it before updating the Company object.
// Uses Prisms to update the position and salary
// Does so in a more efficient manner
let updatePosition' company employeeNo newPosition newSalary =
// The problem with updatePosition above is that it constructs a new company
// object with position updated and then another one with the salary updated
// A faster approach is to navigate to the employee and once found
// update both the position and the salary
// Updates an employee position & salary
let updater = function
| None -> None
| Some e -> { e with Position = newPosition; Salary = newSalary} |> Some
company
// The path to the employee
|> update (Company._Employees >-> lookup employeeNo) updater
In conclusion; the implementation given here is intended to be a starting point for perhaps a different way of thinking on how to work with nested immutable structures. There are some issues with the implementation (like knowing if and why an update failed). This is solvable but I didn't want to pollute the idea with lots of worries.
Hopefully you found it interesting.
Full sample code:
// A Prism consists of two parts
// a getter that gets a property of a value (might return None)
// a setter that sets a property of a value (returns a new instance)
type [<Struct>] Prism<'T, 'U> = Prism of ('T -> 'U option)*('T -> 'U -> 'T)
module Prism =
let inline prism g s = Prism (g, s)
let inline prism' s g = Prism (g, s)
// join joins two Prisms into a new Prism, this is how we navigate nested structures
// Note: Creates in addition to a nested getter also a nested setter so a Prism
// allows both getting and setting of nested properties
let inline join (Prism (tg, ts)) (Prism (ug, us)) =
let getter t =
match tg t with
| None -> None
| Some tv -> ug tv
let setter t v =
match tg t with
| None -> t
| Some tv -> ts t (us tv v)
prism getter setter
// Prism that allows us to navigate Maps
let inline lookup key =
let getter m = Map.tryFind key m
let setter m v = Map.add key v m
prism getter setter
// Given a Prism and a value returns the nested property pointed out by the prism
let get (Prism (tg, _)) t = tg t
// Given a Prism and a value sets the nested property pointed out by the prism
let set (Prism (_, ts)) v t = ts t v
// Given a Prism and a value allows an update function to see the nested property
// and return update it
let update (Prism (tg, ts)) u t =
match u (tg t) with
| None -> t
| Some tv -> ts t tv
type Prism<'T, 'U> with
static member inline ( >-> ) (t, u) = Prism.join t u
module Demo =
open System
open Prism
// Our Domain Model
type [<Struct>] EmployeeNo = EmployeeNo of int
type Position = Contractor | IndividualContributor | Manager
// So prisms enforces some measure of boiler plating.
// Can be mitigated by code generations and possibly type providers
type Employee =
{
No : EmployeeNo
Name : string
Email : string
Hired : DateTime
Salary : decimal
Position : Position
}
// Define Prisms for properties of Employee
static member _No = prism' (fun t v -> { t with No = v }) (fun t -> t.No |> Some)
static member _Name = prism' (fun t v -> { t with Name = v }) (fun t -> t.Name |> Some)
static member _Email = prism' (fun t v -> { t with Email = v }) (fun t -> t.Email |> Some)
static member _Hired = prism' (fun t v -> { t with Hired = v }) (fun t -> t.Hired |> Some)
static member _Salary = prism' (fun t v -> { t with Salary = v }) (fun t -> t.Salary |> Some)
static member _Position = prism' (fun t v -> { t with Position = v }) (fun t -> t.Position |> Some)
type Company =
{
Name : string
Employees : Map<EmployeeNo, Employee>
}
// Define Prisms for properties of Company
static member _Name : Prism<Company, _> = prism' (fun t v -> { t with Name = v }) (fun t -> t.Name |> Some)
static member _Employees : Prism<Company, _> = prism' (fun t v -> { t with Employees = v }) (fun t -> t.Employees |> Some)
open Prism
// Uses Prisms to update the email
let updateEmail company employeeNo newEmail =
company
// The path to the Employee email
|> set (Company._Employees >-> lookup employeeNo >-> Employee._Email) newEmail
// Uses Prisms to update the position and salary
let updatePosition company employeeNo newPosition newSalary =
company
// The path to the Employee position
|> set (Company._Employees >-> lookup employeeNo >-> Employee._Position) newPosition
// The path to the Employee salary
|> set (Company._Employees >-> lookup employeeNo >-> Employee._Salary ) newSalary
// Uses Prisms to update the position and salary
// Does so in a more efficient manner
let updatePosition' company employeeNo newPosition newSalary =
// The problem with updatePosition above is that it constructs a new company
// object with position updated and then another one with the salary updated
// A faster approach is to navigate to the employee and once found
// update both the position and the salary
// Updates an employee position & salary
let updater = function
| None -> None
| Some e -> { e with Position = newPosition; Salary = newSalary} |> Some
company
// The path to the employee
|> update (Company._Employees >-> lookup employeeNo) updater
let test () =
// The initial state of the company
let company : Company =
let e no name email year month day salary position =
let eno = EmployeeNo no
let e : Employee =
{
No = eno
Name = name
Email = email
Hired = DateTime (year, month, day)
Salary = salary
Position = position
}
eno, e
let es =
[|
e 1 "Bill Gates" "billg#microsoft.com" 1979 1 1 100000M Manager
e 2 "Melinda Gates" "melindag#microsoft.com" 1985 6 6 20000M IndividualContributor
|] |> Map.ofArray
{ Name = "Microsoft"; Employees = es}
// Does some organizational changes of the company
printfn "Initial: %A" company
let company = updateEmail company (EmployeeNo 1) "billg#hotmail.com"
printfn "Changing Bill Gates email: %A" company
let company = updatePosition company (EmployeeNo 2) Manager 200000M
printfn "Promoting Melinda Gates: %A" company
let company = updatePosition' company (EmployeeNo 1) IndividualContributor 10000M
printfn "Demoting Bill Gates: %A" company

How do I filter a list in Haskell based on a particular elements value?

I have a list of type Film, where Film(Director Title Year Likes Dislikes), which corresponds to Film -> String -> String -> Int -> [String] -> [String].
I also have a function that takes in the likes and dislikes lists and returns a percentage rating, as such that:
rating :: Likes -> Dislikes -> Int
rating likes dislikes = (((length [likes]) / ((length [dislikes]) + (length [likes]))) * 100)
My problem:
I cannot work out how to use filter to sort this list, to determine whether or not each film's rating is 75% or over.
This is my current attempt:
filterFilm :: Film -> Bool
filterFilm (Film t d y likes dislikes)
| (rating likes dislikes) > 74 = True
| otherwise = False
-- List film rating with and over 75%
listRating :: Database -> Database
listRating (x:xs) = filter (filterFilm x) (x:xs)
I get this error:
Cw 2018.hs:87:29: error:
• Couldn't match expected type ‘Film -> Bool’
with actual type ‘Bool’
• Possible cause: ‘filterFilm’ is applied to too many arguments
In the first argument of ‘filter’, namely ‘(filterFilm x)’
In the expression: filter (filterFilm x) (x : xs)
In an equation for ‘listRating’:
listRating (x : xs) = filter (filterFilm x) (x : xs)
|
87 | listRating (x:xs) = filter (filterFilm x) (x:xs) |
Any suggestions? Thanks in advance!
I think you use filter the wrong way. filter is a function that takes two parameters, the first one a predicate a -> Bool and the second one a list of as.
Now the parameter that is passed to listRating is that list, so listRating l, and you thus call the filter with filter filterFilm l, so:
listRating :: Database -> Database
listRating l = filter filterFilm l
We can also remove the l parameter both in the head and body of the function, like:
listRating :: Database -> Database
listRating = filter filterFilm
Note that you can simplify your filterFilm function to:
filterFilm :: Film -> Bool
filterFilm (Film t d y likes dislikes) = rating likes dislikes > 74

Filtering User-Defined Types

I am attempting to write a function that accepts a list of Artists and a Genre string as parameters and outputs all Artists with that genre. I have defined the data type Artist as follows:
data Artist = Artist Name Genres
deriving Show
type Name = String
type Genres = [Genre]
type Genre = String
My code to implement the function is as follows:
getFilteredArtists :: [Artist] -> Genre -> [Artist]
getFilteredArtists xs genre = filter (genre) (map getGenres xs)
A sample function call is below:
artists = [
Artist "Grimes" ["Electropop", "Dream Pop", "Synthpop"],
Artist "My Bloody Valentine" ["Shoegaze", "Noise Pop", "Post Punk"],
Artist "David Bowie" ["Art Rock", "Pop Rock", "Glam Rock", "New Wave"]
]
getFilteredArtists artists "Art Rock"
Which should return [Artist "David Bowie" ["Art Rock", "Pop Rock", "Glam Rock", "New Wave"]
My function, however, is outputting a type-matching error and I am unsure why. Any help is greatly appreciated!
The below code should work. It would help if you post the type error so people can have a better idea at what's going on. I can see a few issues with your code.
One, you're trying to filter on genre, which is a string, not a bool. You need to use (==) to compare strings.
Second, getGenres isn't defined but assuming it takes an artist, and returns all the genres, mapping it over the artists wouldn't do what your code appears to want it to do. It would just give you the genres without the added context of the artists.
I think what you want to do is filter the artists where the genre is an element of the current artists.
You can also use a data declaration to make automatically make accessor functions for you without having to manually write them.
data Artist = Artist {
getName :: String,
getGenres :: Genres
} deriving (Show)
type Name = String
type Genres = [Genre]
type Genre = String
getFilteredArtists :: [Artist] -> Genre -> [Artist]
getFilteredArtists xs genre = filter (\x -> genre `elem` getGenres x) xs
artists = [
Artist "Grimes" ["Electropop", "Dream Pop", "Synthpop"],
Artist "My Bloody Valentine" ["Shoegaze", "Noise Pop", "Post Punk"],
Artist "David Bowie" ["Art Rock", "Pop Rock", "Glam Rock", "New Wave"]
]
main = print $ getFilteredArtists artists "Art Rock"
The above code will output:
[Artist {getName = "David Bowie", getGenres = ["Art Rock","Pop Rock","Glam Rock","New Wave"]}]
genre :: Genre
filter :: (a -> Bool) -> [a] -> [a]
filter genre :: ???
Instead, what you need is a predicate like
getFilteredArtists xs genre = filter hasGenre xs where
hasGenre :: Artist -> Bool
How to write hasGenre? Well, you already have a getGenres function, and the standard library has a
elem :: Eq a => a -> [a] -> Bool
function. genre `elem` genres == True if genre is contained in genres, False otherwise.

Haskell: filter and sort using input values

so I'm creating a program that will pick one of two libraries (audio.lhs or video.lhs) and will return a pdf with a list ordered and filtered by a given category:
mymain = do {putStrLn "What do you wanna search, Video or Audio?";
tipo <- getLine;
if tipo == "Audio"
then do {
a <- readFile "audio.lhs" ;
let text = splitEvery 7 (splitRegex (mkRegex "\t") a)
list = map musicFile text
select = filter ((>1000) .size) list
orderList = sortBy (comparing title)
dir = Dir orderList
hs = "import Dir\nimport TeX\nimport System.Cmd"
++ "\ntoTeX= do { writeFile \"out.tex\" $ prettyprint dat ;"
++ "system \"pdflatex out\"}"
++ "\ndat="
++ show dir
in do { writeFile "dat.hs" hs ;
putStrLn "\nOk.\nNow load \'dat.hs\' and run \'toTeX\'\n"
}}...
Everything is running but now i need that the functions
select = filter ((>1000) .size) list
and
orderList = sortBy (comparing title)
instead of working with values that are given by me, i want them to work with values choosen by the user of the program (inputs), so if he wants to filter files that are >2000 or <500 is his choice and same with the category,size or title or another thing.
My data structure is
data File = File {
filename :: String ,
size :: Int ,
filetype :: String ,
copyright :: String ,
title :: String ,
artist :: String ,
year :: String } deriving Show
and
musicFile :: [String] -> File
musicFile [name, size, tipo, copy, title, artist, year] = File name (read size) tipo copy title artist year
Any help would be gladly appreciated.
Thanks in advance.
The simplest mechanism available in Haskell for parsing strings is the Read typeclass. Instances of this class have enough functionality to implement
read :: (Read a) => String -> a
readLn :: (Read a) => IO a
either of which should be enough to get you started on your way to reading an Int (which is an instance of Read) from input.

Filter a list of my own type - Tuples?

How can I filter a list of this type by the third item in the tuple:
type Car = (String, [String], Int [String])
I saw the snd and fst methods but here i dont think this will work and im not sure how to map without using the '_' wildcard.
There aren't any pre-defined functions like fst or snd for tuples with more than two elements. As you said, you can use pattern matching and the wild card _ to do the job.
cars = [ ("Foo", ["x", "y"], 2009, ["ab", "cd"]
, ("Bar", ["z"], 1997, [])
]
newCars = filter condition cars
where condition (_, _, n, _) = n > 2005
However, this is usually a sign that you should change from using tuples to a record type.
data Car = Car { model :: String
, foo :: [String]
, year :: Int
, bar :: [String]
}
cars = [ Car "Foo" ["x", "y"] 2009 ["ab", "cd"]
, Car "Bar" ["z"] 1997 []
]
Now, you can use model, foo, year and bar like you would use fst and snd on tuples.
newCars = filter ((> 2005) . year) cars
Or you could just use Data.Tuple.Utils?
MissingH is full of other good stuff too; almost all of my projects use it somewhere or other.
Here is my solution for a similar problem:
--construct a list of stock records with the number in stock less than the reorder level.
getstock (name, stock, reorder) = stock
getreorder (name, stock, reorder) = reorder
check l = filter (\x ->(getstock x < getreorder x)) l
main = print(check [("RAM",9,10),("ROM",12,10),("PROM",20,21)]); --[("RAM",9,10),("PROM",20,21)]
The key was to understand that the filter function takes a predicate, not a boolean value.
So, simply saying
filter(getstock < getreorder)
would not work,
while
`filter (getstock < 10)
would