Question

In haskell, I tried this:

multi::(Num n)=>n->((a->a)->(a->a))
(multi 0) f x=x
(multi n) f x=(multi n-1) f (f x)

Hoping to get a function that would repeat another function a number of times. In ghci I got this:

[1 of 1] Compiling Main             ( pad.hs, interpreted )

pad.hs:2:8:
    Could not deduce (Eq n) arising from the literal `0'
    from the context (Num n)
      bound by the type signature for
                 multi :: Num n => n -> (a -> a) -> a -> a
      at pad.hs:1:8-35
    Possible fix:
      add (Eq n) to the context of
        the type signature for multi :: Num n => n -> (a -> a) -> a -> a
    In the pattern: 0
    In an equation for `multi': multi 0 f x = x

pad.hs:3:23:
    Could not deduce (Num ((a -> a) -> a -> a))
      arising from a use of `-'
    from the context (Num n)
      bound by the type signature for
                 multi :: Num n => n -> (a -> a) -> a -> a
      at pad.hs:1:8-35
    Possible fix:
      add an instance declaration for (Num ((a -> a) -> a -> a))
    In the expression: multi n - 1
    In the expression: (multi n - 1) f (f x)
    In an equation for `multi': multi n f x = (multi n - 1) f (f x)
Failed, modules loaded: none.

I am a newbie to haskell. What do I do?

Was it helpful?

Solution 2

You almost did it. A minimal fix is to add parentheses around n - 1 and remove the signature:

(multi 0) f x=x
(multi n) f x=(multi (n-1)) f (f x)

OTHER TIPS

Couple things. You can't check Num s for equality. You are probably looking for an Int. Second you don't need the parantheses around multi and it's argument. And some other formatting.

multi :: Int -> (a -> a) -> a -> a
multi 0 f x = x
multi n f x = multi (n-1) f (f x)

You could make this type signature more generic, but we will just stick with that. But you can write this whole thing with higher order functions.

multi :: Int -> (a -> a) -> a -> a
multi n f a = foldl (\v _ -> f v) a [1..n]

The smallest change I can make to your program that makes it compile is:

multi::(Eq n, Num n)=>n->((a->a)->(a->a))
(multi 0) f x=x
(multi n) f x=(multi (n-1)) f (f x)

The Num type class doesn't require members to already be members of Eq, so we have to specify that as well. Additionally, we want to pass n-1 as an argument to multi.

This problem is normally done in Haskell land with iterate and !!.

There are a couple things wrong here.

Num n does not imply Eq n, meaning there is no Eq n => Num n constraint in the Num typeclass definition. In order to pattern match on 0 you need the n type to be an instance of Eq. I would just explicitly change this to Int, there is no reason for the extra generality in this piece of code.

Next, (multi n-1) applies multi to n then subtracts 1.b I've also cleaned up the code and put the parens in the right places.

multi:: Int -> (a -> a) -> a -> a
multi 0 _ x = x
multi n f x = multi (n-1) f (f x)

As Cirdec points out you can do this with iterate f a !! n.

Edit:

If what you're trying to do is get a function that is f applied n times you can do something like this. Replacing 10 with n and (1+) with whatever function you wanted repeated. (or just partially apply multi)

let f = foldr1 (.) (take 10 $ repeat (1+))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top