Reputation: 13
I have a question about on how to change only one case of this structure:
type Foo a = String -> a
--Let's define a function.
foo :: Foo Int
foo "a" = 5
foo "b" = 6
foo "c" = 7
foo x = 0
Now suppose I want to create another function that gives me another function but only changed in one case, this is what I did.
changeFoo :: Foo a -> String -> a -> Foo a
changeFoo = \foo -> \str -> \x -> (\str -> \x)
I'm new at programming Haskell and this doesn't seem to change only one case of the function. If someone can tell me what to do I'll be grateful.
Thanks in advance.
Upvotes: 0
Views: 244
Reputation: 27776
This solution is a bit overkill and only worth it if you already use the lens
library in your project, but module Control.Lens.Prism
offers a way to define "setters" for functions that override the behaviour of the functions for particular input values.
Suppose that we want we override the behaviour for "c" in your case. We begin by defining a Prism
for "c"
using only
:
only "c"
-- This Prism compares for exact equality with a given value.
Then we build the "Setter
for functions" using outside
:
outside $ only "c"
The whole new definition:
foo' :: Foo Int
foo' = set (outside $ only "c") (\_ -> 77) foo
Testing it:
foo' "c"
>>> 77
Upvotes: 2
Reputation: 1441
You need to check if the strings are equal or not. Something like
changeFoo :: (String -> Int) -> String -> Int -> String -> Int
changeFoo f s1 a s2
| s1 == s2 = a
| otherwise = f s2
I think changeFoo can be given a more general type though:
changeFoo :: Eq a => (a -> b) -> a -> b -> a -> b
Another way to write it even more generically is with the maybe type:
changeFoo :: (a -> b) -> (a -> Maybe b) -> a -> b
But that will clearly require a different implementation.
Upvotes: 3