I am currently learning haskell, trying to make a function successor
either takes in a Num
and returns its successor (4 == successor 3
) or takes in itself and returns a double successor function (5 == (successor successor) 3
).
What would be the correct way to make successor
function is a type of its class Successor
?
naive Successor
class
class Successor a where
successor :: a -> a
instance Successor Int where
successor n
| (==) 1 n = 2
| otherwise = 1 successor (n - 1)
test code
n :: Int
n = 3
m = successor (successor n)
main = do
print m -- print 5
needed behavior
n :: Int
n = 3
m = (successor successor) n
main = do
print m -- print 5
CodePudding user response:
This seems an awful idea to me -- why do you want to write a function working on both numbers and functions?
Anyway, you could achieve what you ask (but probably not what you really want) as follows:
{-# LANGUAGE FlexibleInstances #-}
module Main where
class Successor a where
successor :: a -> a
instance Successor Int where
successor n
| (==) 1 n = 2
| otherwise = 1 successor (n - 1)
instance Successor (Int -> Int) where
successor f = f . f
n' :: Int
n' = 3
m1 :: Int
m1 = successor (successor n')
m2 :: Int
m2 = (successor successor) n'
main :: IO ()
main = do
print m1 -- print 5
print m2 -- print 5
The definition successor f = f . f
works in this specific case, where f = successor
, but will likely not produce the expected output in other cases.
We could use some variant like successor f = successor . f
. Perhaps this is more useful in general, but it still looks as a bad idea to me.
CodePudding user response:
I agree with chi that this is probably a bad idea, but if you're going to have such a typeclass then I'd make it as general as possible:
class Successor a where
scs :: a -> a
instance Successor Int where
scs = succ -- don't reinvent the wheel
instance Successor a => Successor (c -> a) where
scs f = scs . f
Then
ghci> scs scs (scs (scs scs)) ((scs scs) scs) scs (scs scs) 0 :: Int
11