Reputation: 31
I want to return None (Or Haskell's equivalent to None, rather) to this list of valid factors and whenever I encounter a number that isn't valid (a number that doesn't return a value of 0 when I run it in the modulus function along with x), I want to return None so that the list only contains the factors. There might be some errors in the code, I am new to Haskell, so you'll have to excuse sloppy code and such.
I've tried using return maybe x, since I heard that it would work, but I had no luck with it (might've been using it incorrectly, though). I also thought about using some kind of standard value and using a seoarate function to filter the values out, but I reckoned that there must be a better way.
import Data.List
import System.IO
checkPerfect x
| x == sum factor x = return x
| otherwise = return None
factor x
| mod x [1..x-1] == 0 = return x
| otherwise = return None
main = do
putStrLn "Upper limit?"
limit <- readLn
let uncheckedNumbers = [1..limit]
let perfectNumbersRaw = map checkPerfect uncheckedNumbers
putStrLn ("Perfect numbers: " ++ perfectNumbersRaw)
Upvotes: 2
Views: 248
Reputation: 477190
Usually a Maybe a
type is used to return a computation that can fail, or an Either String a
where the Left
constructor returns an error message.
Note that Haskell has no return
statement. return
is a function that is used for monads. Strictly speaking, you can use return
here to wrap the result in a Just
constructor, but it is probably more readable to do that explicitly.
That being said, your program has a lot of problems, both syntactically and semantically:
x == sum factor x
will not calculate the sum of the factors/divisors, since factor
will return a single number (probably wrapped in a Maybe
), yes, you can calculate the sum of a Num a => Maybe a
type, but that is the sum of the only item it wraps, or 0
in case of a Nothing
;return
here in the first place, Haskell has no return
statement;show :: Show a => a -> String
to convert it to a string;map checkPerfect
you will generate a list that contains for each item a Just x
or a Nothing
, you probably want to use filter
instead.I think it makes more sense here to return a Bool
instead, and then filter the list:
checkPerfect :: Integral i => i -> Bool
checkPerfect x = x == sum (filter ((==) 0 . mod x) [1 .. x-1])
or as @melpomene says with list comprehension:
checkPerfect :: Integral i => i -> Bool
checkPerfect x = x == sum [ k | k <- [1 .. x-1], mod x k == 0 ]
and then print the list of items with:
main = do
putStrLn "Upper limit?"
limit <- readLn :: IO Int
putStrLn ("Perfect numbers: " ++ show (filter checkPerfect [1 .. limit]))
If we take as limit 10'000, we get:
Prelude> main
Upper limit?
10000
Perfect numbers: [6,28,496,8128]
Upvotes: 11
Reputation: 15887
The Maybe type is the primary optional type in Haskell. For instance, you could use Just x
and Nothing
, or using its Monad, return x
and fail "not perfect"
. Note that return
is a function of monads, moving values from pure (which is frequently the Applicative name for the same function) to monadic, and not needed when you don't need to wrap a value.
Upvotes: 4