Reputation: 2967
I have the following data type:
data Users = Height Int | Age Int
I then have a list of ages:
myList = [Age 44, Age 54, Age 21, Age 34, Age 22]
Which I want to apply to this function:
myFunction :: [Users] -> [Users]
myFunction li = [x + 1 | x <- li]
However this causes the following error:
"No instance for (Num Users) arising from a use of ‘+’"
How can I make this work? Do I need to separate 'Age' from each of the values?
Upvotes: 1
Views: 244
Reputation: 2967
I've found the best solution using Applicative Functors.
Code:
data Users a = Height a | Age a deriving (Show, Eq, Ord)
myList = [Age 44, Age 65, Age 21, Age 87]
instance Functor Users where
fmap f (Age a) = Age (f a)
fmap f (Height a) = Height (f a)
instance Applicative Users where
pure a = (Age a)
(<*>) (Age a) = fmap a
pure a = (Height a)
(<*>) (Height a) = fmap a
main = do
let increaseAgesByOne = pure (\x -> pure (+1) <*> x) <*> myList
print $ increaseAgesByOne
Output:
[Age 45, Age 66, Age 22, Age 88]
Hope this helps anyone with a similar problem.
Upvotes: -1
Reputation: 22273
In your case I think you don't really want a new data type
data Users = Height Int | Age Int
Type synonyms should suffice; they will work nicely with standard operators:
type Age = Int
type Height = Int
myList :: [Age]
myList = [44, 54, 21, 34, 22]
myFunction :: [Age] -> [Age]
myFunction li = [x + 1 | x <- li]
Upvotes: 2
Reputation: 2048
@Schoon is right.
But if you want to make it on your way you can do this:
data Users = Height Int | Age Int deriving (Show)
you have to "derive" show ;)
then:
older :: Users -> Users
older (Age a) = Age (a+1)
older _ = error "not Age" --Now it's better ;)
and your function:
everyOneOlder :: [Users] -> [Users]
everyOneOlder li = [older x | x <- li]
And then, you become this:
*Main> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> let x = Age 5
*Main> x
Age 5
*Main> let y = older x
*Main> y
Age 6
*Main> let z = [Age 1, Age 2]
*Main> everyOneOlder z
[Age 2,Age 3]
*Main>
Nice, isn't it? :)
Upvotes: 1
Reputation: 394
First, the error message tells you that you are using the (+)
function on Users
, for which it is not defined.
So you could make Users
an instance of Num
, meaning that you also need to define (-)
, (*)
, negate
,.. for Users
, which seems odd.
Maybe you need something like this:
data User = User {height :: Int, age :: Int } deriving (Show)
addToHeight :: Int -> User -> User
addToHeight x (User h a) = User (h+x) a
then use:
let users = [User 180 20, User 185 22]
fmap (addToHeight 1) users
--
to leave semantics aside:
plus :: Int -> Users -> Users
plus x (Age a) = Age (a+x)
plus x (Height h) = Height (h+x)
Upvotes: 8