How to curry functions in Haskell
I have a function multThree for multiplying 3 numbers which works with currying. However, when I tried extending this to multiplying four numbers using the same structure it doesn't work. Why is this and how could it be fixed?
multThree :: Num a => a -> (a -> (a -> a))
multThree x = (*) . (*) x
multFour :: Num a => a -> (a -> (a -> (a -> a)))
multFour x = (*) . (*) . (*) x
Error given:
• Occurs check: cannot construct the infinite type: a ~ a -> a
Expected type: a -> a -> a -> a
Actual type: a -> (a -> a) -> a -> a
• In the expression: (*) . (*) . (*) x
In an equation for ‘multFour’: multFour x = (*) . (*) . (*) x
• Relevant bindings include
x :: a (bound at test2.hs:19:10)
multFour :: a -> a -> a -> a -> a
haskell currying
add a comment |
I have a function multThree for multiplying 3 numbers which works with currying. However, when I tried extending this to multiplying four numbers using the same structure it doesn't work. Why is this and how could it be fixed?
multThree :: Num a => a -> (a -> (a -> a))
multThree x = (*) . (*) x
multFour :: Num a => a -> (a -> (a -> (a -> a)))
multFour x = (*) . (*) . (*) x
Error given:
• Occurs check: cannot construct the infinite type: a ~ a -> a
Expected type: a -> a -> a -> a
Actual type: a -> (a -> a) -> a -> a
• In the expression: (*) . (*) . (*) x
In an equation for ‘multFour’: multFour x = (*) . (*) . (*) x
• Relevant bindings include
x :: a (bound at test2.hs:19:10)
multFour :: a -> a -> a -> a -> a
haskell currying
4
This isn't about currying (multThreeis already curried, as its type isa -> a -> a -> a, not(a, a, a) -> a); it's about composing higher-order functions.
– chepner
Jan 2 at 12:56
The hideous point-free form ofmultThreewould bemultThree = ((*) .) . (*), which (to be honest), is barely worth understanding instead of simply writing the non-point-free version. (multFour = ((((*) .) . (*)) .) . (*)is even worse.)
– chepner
Jan 2 at 18:44
If you really want a point-free version, you could usemultThree = fmap (*) . (*)andmultFour = fmap (fmap (*)) . fmap (*) . (*)=fmap (fmap (*) . (*)) . (*)=fmap multThree . (*). Thefmapis the same as(.)but in my opinion makes it a little clearer where you’re “skipping over” arguments. Another way to build a point-free solution is e.g.multThree = curry ((*) . uncurry (*)): you’re pairing up two arguments in a tuple, multiplying them together, then multiplying the result by the other argument.
– Jon Purdy
Jan 5 at 0:00
add a comment |
I have a function multThree for multiplying 3 numbers which works with currying. However, when I tried extending this to multiplying four numbers using the same structure it doesn't work. Why is this and how could it be fixed?
multThree :: Num a => a -> (a -> (a -> a))
multThree x = (*) . (*) x
multFour :: Num a => a -> (a -> (a -> (a -> a)))
multFour x = (*) . (*) . (*) x
Error given:
• Occurs check: cannot construct the infinite type: a ~ a -> a
Expected type: a -> a -> a -> a
Actual type: a -> (a -> a) -> a -> a
• In the expression: (*) . (*) . (*) x
In an equation for ‘multFour’: multFour x = (*) . (*) . (*) x
• Relevant bindings include
x :: a (bound at test2.hs:19:10)
multFour :: a -> a -> a -> a -> a
haskell currying
I have a function multThree for multiplying 3 numbers which works with currying. However, when I tried extending this to multiplying four numbers using the same structure it doesn't work. Why is this and how could it be fixed?
multThree :: Num a => a -> (a -> (a -> a))
multThree x = (*) . (*) x
multFour :: Num a => a -> (a -> (a -> (a -> a)))
multFour x = (*) . (*) . (*) x
Error given:
• Occurs check: cannot construct the infinite type: a ~ a -> a
Expected type: a -> a -> a -> a
Actual type: a -> (a -> a) -> a -> a
• In the expression: (*) . (*) . (*) x
In an equation for ‘multFour’: multFour x = (*) . (*) . (*) x
• Relevant bindings include
x :: a (bound at test2.hs:19:10)
multFour :: a -> a -> a -> a -> a
haskell currying
haskell currying
asked Jan 2 at 12:08
KhamKham
85
85
4
This isn't about currying (multThreeis already curried, as its type isa -> a -> a -> a, not(a, a, a) -> a); it's about composing higher-order functions.
– chepner
Jan 2 at 12:56
The hideous point-free form ofmultThreewould bemultThree = ((*) .) . (*), which (to be honest), is barely worth understanding instead of simply writing the non-point-free version. (multFour = ((((*) .) . (*)) .) . (*)is even worse.)
– chepner
Jan 2 at 18:44
If you really want a point-free version, you could usemultThree = fmap (*) . (*)andmultFour = fmap (fmap (*)) . fmap (*) . (*)=fmap (fmap (*) . (*)) . (*)=fmap multThree . (*). Thefmapis the same as(.)but in my opinion makes it a little clearer where you’re “skipping over” arguments. Another way to build a point-free solution is e.g.multThree = curry ((*) . uncurry (*)): you’re pairing up two arguments in a tuple, multiplying them together, then multiplying the result by the other argument.
– Jon Purdy
Jan 5 at 0:00
add a comment |
4
This isn't about currying (multThreeis already curried, as its type isa -> a -> a -> a, not(a, a, a) -> a); it's about composing higher-order functions.
– chepner
Jan 2 at 12:56
The hideous point-free form ofmultThreewould bemultThree = ((*) .) . (*), which (to be honest), is barely worth understanding instead of simply writing the non-point-free version. (multFour = ((((*) .) . (*)) .) . (*)is even worse.)
– chepner
Jan 2 at 18:44
If you really want a point-free version, you could usemultThree = fmap (*) . (*)andmultFour = fmap (fmap (*)) . fmap (*) . (*)=fmap (fmap (*) . (*)) . (*)=fmap multThree . (*). Thefmapis the same as(.)but in my opinion makes it a little clearer where you’re “skipping over” arguments. Another way to build a point-free solution is e.g.multThree = curry ((*) . uncurry (*)): you’re pairing up two arguments in a tuple, multiplying them together, then multiplying the result by the other argument.
– Jon Purdy
Jan 5 at 0:00
4
4
This isn't about currying (
multThree is already curried, as its type is a -> a -> a -> a, not (a, a, a) -> a); it's about composing higher-order functions.– chepner
Jan 2 at 12:56
This isn't about currying (
multThree is already curried, as its type is a -> a -> a -> a, not (a, a, a) -> a); it's about composing higher-order functions.– chepner
Jan 2 at 12:56
The hideous point-free form of
multThree would be multThree = ((*) .) . (*), which (to be honest), is barely worth understanding instead of simply writing the non-point-free version. (multFour = ((((*) .) . (*)) .) . (*) is even worse.)– chepner
Jan 2 at 18:44
The hideous point-free form of
multThree would be multThree = ((*) .) . (*), which (to be honest), is barely worth understanding instead of simply writing the non-point-free version. (multFour = ((((*) .) . (*)) .) . (*) is even worse.)– chepner
Jan 2 at 18:44
If you really want a point-free version, you could use
multThree = fmap (*) . (*) and multFour = fmap (fmap (*)) . fmap (*) . (*) = fmap (fmap (*) . (*)) . (*) = fmap multThree . (*). The fmap is the same as (.) but in my opinion makes it a little clearer where you’re “skipping over” arguments. Another way to build a point-free solution is e.g. multThree = curry ((*) . uncurry (*)): you’re pairing up two arguments in a tuple, multiplying them together, then multiplying the result by the other argument.– Jon Purdy
Jan 5 at 0:00
If you really want a point-free version, you could use
multThree = fmap (*) . (*) and multFour = fmap (fmap (*)) . fmap (*) . (*) = fmap (fmap (*) . (*)) . (*) = fmap multThree . (*). The fmap is the same as (.) but in my opinion makes it a little clearer where you’re “skipping over” arguments. Another way to build a point-free solution is e.g. multThree = curry ((*) . uncurry (*)): you’re pairing up two arguments in a tuple, multiplying them together, then multiplying the result by the other argument.– Jon Purdy
Jan 5 at 0:00
add a comment |
1 Answer
1
active
oldest
votes
Let’s write it out without (.):
multFour x = (*) . (*) . (*) x
= (*) . (y -> (y*)) . (x*)
= (w -> (w*)) . (z -> ((x*z)*))
= (w -> (w*)) . (z v -> x*z*v)
= z -> u -> (v -> x*z*v) * u
And so we see that we are trying to multiply a function by a number.
The key error is this:
multFour x = (*) . multThree x
And the types are:
(*) :: Num a => a -> (a -> a)
multThree x :: Num b => b -> (b -> b)
x :: b
(.) :: (y -> z) -> (x -> y) -> (x -> z)
So the types unify as:
a = y
z = (a -> a)
b = x
y = b -> b
multFour :: Num b => b -> x -> z
multFour :: (Num b, Num (b -> b)) => b -> b -> (b -> b) -> (b -> b)
Which is not the type you want it to be.
To fix your code, I recommend:
multFour a b c d = a * b * c * d
This is much more readable.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54006099%2fhow-to-curry-functions-in-haskell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Let’s write it out without (.):
multFour x = (*) . (*) . (*) x
= (*) . (y -> (y*)) . (x*)
= (w -> (w*)) . (z -> ((x*z)*))
= (w -> (w*)) . (z v -> x*z*v)
= z -> u -> (v -> x*z*v) * u
And so we see that we are trying to multiply a function by a number.
The key error is this:
multFour x = (*) . multThree x
And the types are:
(*) :: Num a => a -> (a -> a)
multThree x :: Num b => b -> (b -> b)
x :: b
(.) :: (y -> z) -> (x -> y) -> (x -> z)
So the types unify as:
a = y
z = (a -> a)
b = x
y = b -> b
multFour :: Num b => b -> x -> z
multFour :: (Num b, Num (b -> b)) => b -> b -> (b -> b) -> (b -> b)
Which is not the type you want it to be.
To fix your code, I recommend:
multFour a b c d = a * b * c * d
This is much more readable.
add a comment |
Let’s write it out without (.):
multFour x = (*) . (*) . (*) x
= (*) . (y -> (y*)) . (x*)
= (w -> (w*)) . (z -> ((x*z)*))
= (w -> (w*)) . (z v -> x*z*v)
= z -> u -> (v -> x*z*v) * u
And so we see that we are trying to multiply a function by a number.
The key error is this:
multFour x = (*) . multThree x
And the types are:
(*) :: Num a => a -> (a -> a)
multThree x :: Num b => b -> (b -> b)
x :: b
(.) :: (y -> z) -> (x -> y) -> (x -> z)
So the types unify as:
a = y
z = (a -> a)
b = x
y = b -> b
multFour :: Num b => b -> x -> z
multFour :: (Num b, Num (b -> b)) => b -> b -> (b -> b) -> (b -> b)
Which is not the type you want it to be.
To fix your code, I recommend:
multFour a b c d = a * b * c * d
This is much more readable.
add a comment |
Let’s write it out without (.):
multFour x = (*) . (*) . (*) x
= (*) . (y -> (y*)) . (x*)
= (w -> (w*)) . (z -> ((x*z)*))
= (w -> (w*)) . (z v -> x*z*v)
= z -> u -> (v -> x*z*v) * u
And so we see that we are trying to multiply a function by a number.
The key error is this:
multFour x = (*) . multThree x
And the types are:
(*) :: Num a => a -> (a -> a)
multThree x :: Num b => b -> (b -> b)
x :: b
(.) :: (y -> z) -> (x -> y) -> (x -> z)
So the types unify as:
a = y
z = (a -> a)
b = x
y = b -> b
multFour :: Num b => b -> x -> z
multFour :: (Num b, Num (b -> b)) => b -> b -> (b -> b) -> (b -> b)
Which is not the type you want it to be.
To fix your code, I recommend:
multFour a b c d = a * b * c * d
This is much more readable.
Let’s write it out without (.):
multFour x = (*) . (*) . (*) x
= (*) . (y -> (y*)) . (x*)
= (w -> (w*)) . (z -> ((x*z)*))
= (w -> (w*)) . (z v -> x*z*v)
= z -> u -> (v -> x*z*v) * u
And so we see that we are trying to multiply a function by a number.
The key error is this:
multFour x = (*) . multThree x
And the types are:
(*) :: Num a => a -> (a -> a)
multThree x :: Num b => b -> (b -> b)
x :: b
(.) :: (y -> z) -> (x -> y) -> (x -> z)
So the types unify as:
a = y
z = (a -> a)
b = x
y = b -> b
multFour :: Num b => b -> x -> z
multFour :: (Num b, Num (b -> b)) => b -> b -> (b -> b) -> (b -> b)
Which is not the type you want it to be.
To fix your code, I recommend:
multFour a b c d = a * b * c * d
This is much more readable.
answered Jan 2 at 12:31
Dan RobertsonDan Robertson
3,313716
3,313716
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54006099%2fhow-to-curry-functions-in-haskell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
This isn't about currying (
multThreeis already curried, as its type isa -> a -> a -> a, not(a, a, a) -> a); it's about composing higher-order functions.– chepner
Jan 2 at 12:56
The hideous point-free form of
multThreewould bemultThree = ((*) .) . (*), which (to be honest), is barely worth understanding instead of simply writing the non-point-free version. (multFour = ((((*) .) . (*)) .) . (*)is even worse.)– chepner
Jan 2 at 18:44
If you really want a point-free version, you could use
multThree = fmap (*) . (*)andmultFour = fmap (fmap (*)) . fmap (*) . (*)=fmap (fmap (*) . (*)) . (*)=fmap multThree . (*). Thefmapis the same as(.)but in my opinion makes it a little clearer where you’re “skipping over” arguments. Another way to build a point-free solution is e.g.multThree = curry ((*) . uncurry (*)): you’re pairing up two arguments in a tuple, multiplying them together, then multiplying the result by the other argument.– Jon Purdy
Jan 5 at 0:00