Reputation: 63
I pretend to create a high order function that uses as one of its parameters a function which belongs to the record of a certain Data Type.
For Example:
type Debt = Float
type Power = Int
Data State = S String Debt
Data City = C String Power Debt
Data Country = Country
{ states :: [State]
, cities :: [City] }
upDetail :: (Country -> [a])
-> ([a] -> b -> [a])
-> b -> Country -> Country
upDetail f g b country = country { f = new }
where old = f country
new = g old b
What the function above is supposed to do is pick an element of the record of the Country (with the function type Country -> [a]
) and alter it according to a certain function type [a] -> b -> [a]
and a certain b
However, when i try to compile this i get an error saying :
‘f’ is not a (visible) constructor field name
Is there any way i can overcome this problem? I thought of using Maybe Country as my result but i don't know how to do this.
Upvotes: 1
Views: 68
Reputation: 89073
As the comments mention, the normal solution to this is to use lenses:
upDetail :: Lens Country [a]
-> ([a] -> b -> [a])
-> b -> Country -> Country
upDetail f g b country = set f country new
where old = get f country
new = g old b
However, lenses aren't that hard to get a handle on, especially for so simple a purpose.
The simplest way of expressing a lens is as a getter and a setter function:
data Lens s a = Lens
{ get :: s -> a
, set :: s -> a -> s
}
_states :: Lens Country [State]
_states = Lens states $ \c new -> c { states = new }
_cities :: Lens Country [City]
_cities = Lens cities $ \c new -> c { cities = new }
This lets us modify the cities or states of a country pretty easily:
λ Country [] []
Country {states = [], cities = []}
λ upDetail _cities (\cs c -> c:cs) (C "Hereford" 100 3000) it
Country {states = [], cities = [C "Hereford" 100 3000.0]}
λ upDetail _states (\cs c -> c:cs) (S "Delmarva" 4) it
Country {states = [S "Delmarva" 4.0], cities = [C "Hereford" 100 3000.0]}
Lens get slightly more complex once you start thinking about composing lenses, which you're not getting into here, but you could.
Upvotes: 5