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)
Вопрос
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?
Решение 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)
Другие советы
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+))