Must the operator for a semigroup be defined for all arguments?












1















Is the example below a correct definition of a semigroup?



instance Semigroup (CurrencyAmount Fixed2) where
(<>) (CurrencyAmount a c) (CurrencyAmount _ EMPTY) = CurrencyAmount a c
(<>) (CurrencyAmount _ EMPTY) (CurrencyAmount a c) = CurrencyAmount a c
(<>) (CurrencyAmount a c1) (CurrencyAmount b c2) | c1 == c2 = CurrencyAmount (a + b) c1
(<>) _ _ = error "currency mismatch"









share|improve this question

























  • The operator should be associative, so you can aim to proof that, and then it is a semigroup.

    – Willem Van Onsem
    Nov 25 '18 at 9:58











  • the operator is associative int this example for valid inputs but the <> operator (or function) is not total in this case and I do not know if this is relevant for the prove or not.

    – rogergl
    Nov 25 '18 at 10:11











  • The definition of CurrencyAmount would be helpful.

    – chepner
    Nov 26 '18 at 13:56
















1















Is the example below a correct definition of a semigroup?



instance Semigroup (CurrencyAmount Fixed2) where
(<>) (CurrencyAmount a c) (CurrencyAmount _ EMPTY) = CurrencyAmount a c
(<>) (CurrencyAmount _ EMPTY) (CurrencyAmount a c) = CurrencyAmount a c
(<>) (CurrencyAmount a c1) (CurrencyAmount b c2) | c1 == c2 = CurrencyAmount (a + b) c1
(<>) _ _ = error "currency mismatch"









share|improve this question

























  • The operator should be associative, so you can aim to proof that, and then it is a semigroup.

    – Willem Van Onsem
    Nov 25 '18 at 9:58











  • the operator is associative int this example for valid inputs but the <> operator (or function) is not total in this case and I do not know if this is relevant for the prove or not.

    – rogergl
    Nov 25 '18 at 10:11











  • The definition of CurrencyAmount would be helpful.

    – chepner
    Nov 26 '18 at 13:56














1












1








1








Is the example below a correct definition of a semigroup?



instance Semigroup (CurrencyAmount Fixed2) where
(<>) (CurrencyAmount a c) (CurrencyAmount _ EMPTY) = CurrencyAmount a c
(<>) (CurrencyAmount _ EMPTY) (CurrencyAmount a c) = CurrencyAmount a c
(<>) (CurrencyAmount a c1) (CurrencyAmount b c2) | c1 == c2 = CurrencyAmount (a + b) c1
(<>) _ _ = error "currency mismatch"









share|improve this question
















Is the example below a correct definition of a semigroup?



instance Semigroup (CurrencyAmount Fixed2) where
(<>) (CurrencyAmount a c) (CurrencyAmount _ EMPTY) = CurrencyAmount a c
(<>) (CurrencyAmount _ EMPTY) (CurrencyAmount a c) = CurrencyAmount a c
(<>) (CurrencyAmount a c1) (CurrencyAmount b c2) | c1 == c2 = CurrencyAmount (a + b) c1
(<>) _ _ = error "currency mismatch"






haskell






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 25 '18 at 10:54









Mark Seemann

183k33325559




183k33325559










asked Nov 25 '18 at 9:51









rogerglrogergl

1,38211737




1,38211737













  • The operator should be associative, so you can aim to proof that, and then it is a semigroup.

    – Willem Van Onsem
    Nov 25 '18 at 9:58











  • the operator is associative int this example for valid inputs but the <> operator (or function) is not total in this case and I do not know if this is relevant for the prove or not.

    – rogergl
    Nov 25 '18 at 10:11











  • The definition of CurrencyAmount would be helpful.

    – chepner
    Nov 26 '18 at 13:56



















  • The operator should be associative, so you can aim to proof that, and then it is a semigroup.

    – Willem Van Onsem
    Nov 25 '18 at 9:58











  • the operator is associative int this example for valid inputs but the <> operator (or function) is not total in this case and I do not know if this is relevant for the prove or not.

    – rogergl
    Nov 25 '18 at 10:11











  • The definition of CurrencyAmount would be helpful.

    – chepner
    Nov 26 '18 at 13:56

















The operator should be associative, so you can aim to proof that, and then it is a semigroup.

– Willem Van Onsem
Nov 25 '18 at 9:58





The operator should be associative, so you can aim to proof that, and then it is a semigroup.

– Willem Van Onsem
Nov 25 '18 at 9:58













the operator is associative int this example for valid inputs but the <> operator (or function) is not total in this case and I do not know if this is relevant for the prove or not.

– rogergl
Nov 25 '18 at 10:11





the operator is associative int this example for valid inputs but the <> operator (or function) is not total in this case and I do not know if this is relevant for the prove or not.

– rogergl
Nov 25 '18 at 10:11













The definition of CurrencyAmount would be helpful.

– chepner
Nov 26 '18 at 13:56





The definition of CurrencyAmount would be helpful.

– chepner
Nov 26 '18 at 13:56












2 Answers
2






active

oldest

votes


















3














I suppose this is a matter of semantics. The formal and classical mathematical definition of a Semigroup (A,<>) does requires <> to be a function <>:A×A→A, therefore total. But what is your set A? You need to establish some (naive) set theoretical based semantics for the (Haskell) types and functions you're working with.




  • If the denotation of your types are carrier sets that include as an element, then your Haskell functions will be interpreted as total mathematical functions. In this case you just have to make sure the required laws hold for all elements including . And in your case they do.


  • If instead you consider a model of sets (without ) and partial functions, then to match the classic formal mathematical definition of Semigroup you'd need to make sure <> is total in that setting. And in your case it isn't.



I don't know whether there is a fixed convention. The second, stricter interpretation seems preferable. But the first is a sensible generalisation.



That said have you considered the possibility of using GADTs to distinguish between different currencies at the type level?






share|improve this answer


























  • Well one can add a dollar to a pound, and have a dollar and a pound. (Like a vector space of currencies).

    – n.m.
    Nov 25 '18 at 13:33











  • I don't think including bottom is a useful approach in practice, as it's hard to manipulate diverging computations. Can you write a unit test that verifies bottom <> bottom == bottom?

    – n.m.
    Nov 25 '18 at 15:08











  • You could say the same for any property involving though, including strictness. Furthermore, it's not that simple to avoid . Consider <> defined on function types. The resulting laws establish equalities on (partial) functions. The Semigroup module itself provides the instance Semigroup b => Semigroup (a -> b) where f <> g = x -> f x <> g x.

    – Jorge Adriano
    Nov 25 '18 at 15:39











  • I can, and I usually do ;) One can reason about the bottom, but one cannot work with it. It is not a useful value --- a program that tries to evaluate it is broken. A program can pass unevaluated bottoms around, but since it cannot look at them, one could replace these bottoms by any other value without affecting the meaning of the program.

    – n.m.
    Nov 25 '18 at 15:59











  • I think I like the vector of currencies approach best.

    – rogergl
    Nov 26 '18 at 8:07



















2














I don't think it's valid.



Most of the lawful type classes in Haskell (e.g. Semigroup, Monoid, Functor, Monad, etc.) derive their laws from mathematics (e.g. category theory).



Mathematics is based on axioms; that is, assertions about the underlying fabric of numbers, geometry, and similar. By definition, axioms can't be proven, but you usually accept them because they make intuitive sense (e.g. the Peano axioms). In a sense, mathematics is built on a foundation of intuition.



The reason that type classes like the above are lawful is that the laws ensure that the instances behave like you'd expect them to behave.



In Haskell, there's great emphasis on being able to reason about the code, mostly by just looking at the type signatures of functions. One reason you, as a reader, can feel confident about doing this is that whenever a lawful type class is involved, you know that it'll behave in a non-surprising manner.



Most mathematical functions are total (there are exceptions, e.g. division by zero, but exceptions should be drawn from mathematics itself). In light of the above, I'd argue that there's a strong implicit expectation that a type class that derives its laws from mathematics is expected to be total.



The above instance isn't total, which means that it'll behave in a surprising manner for certain inputs. I wouldn't consider it a valid Semigroup instance.






share|improve this answer


























  • Yeah. Division.

    – n.m.
    Nov 25 '18 at 10:56











  • @n.m. What about division?

    – Mark Seemann
    Nov 25 '18 at 10:57






  • 1





    Is it total? What's its domain? To what Haskell type does said domain correspond?

    – n.m.
    Nov 25 '18 at 10:59













  • @n.m. It's not uncommon in mathematics that functions can be "undefined" at points not in its domain. Do we consider the zero denominator part of the division function's domain?

    – Mark Seemann
    Nov 25 '18 at 11:07











  • @n.m. Not that I don't get your point. In Haskell, division is clearly not total, so it does invalidate my argument. Do you, however, find the OP instance valid?

    – Mark Seemann
    Nov 25 '18 at 11:08











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
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53466359%2fmust-the-operator-for-a-semigroup-be-defined-for-all-arguments%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














I suppose this is a matter of semantics. The formal and classical mathematical definition of a Semigroup (A,<>) does requires <> to be a function <>:A×A→A, therefore total. But what is your set A? You need to establish some (naive) set theoretical based semantics for the (Haskell) types and functions you're working with.




  • If the denotation of your types are carrier sets that include as an element, then your Haskell functions will be interpreted as total mathematical functions. In this case you just have to make sure the required laws hold for all elements including . And in your case they do.


  • If instead you consider a model of sets (without ) and partial functions, then to match the classic formal mathematical definition of Semigroup you'd need to make sure <> is total in that setting. And in your case it isn't.



I don't know whether there is a fixed convention. The second, stricter interpretation seems preferable. But the first is a sensible generalisation.



That said have you considered the possibility of using GADTs to distinguish between different currencies at the type level?






share|improve this answer


























  • Well one can add a dollar to a pound, and have a dollar and a pound. (Like a vector space of currencies).

    – n.m.
    Nov 25 '18 at 13:33











  • I don't think including bottom is a useful approach in practice, as it's hard to manipulate diverging computations. Can you write a unit test that verifies bottom <> bottom == bottom?

    – n.m.
    Nov 25 '18 at 15:08











  • You could say the same for any property involving though, including strictness. Furthermore, it's not that simple to avoid . Consider <> defined on function types. The resulting laws establish equalities on (partial) functions. The Semigroup module itself provides the instance Semigroup b => Semigroup (a -> b) where f <> g = x -> f x <> g x.

    – Jorge Adriano
    Nov 25 '18 at 15:39











  • I can, and I usually do ;) One can reason about the bottom, but one cannot work with it. It is not a useful value --- a program that tries to evaluate it is broken. A program can pass unevaluated bottoms around, but since it cannot look at them, one could replace these bottoms by any other value without affecting the meaning of the program.

    – n.m.
    Nov 25 '18 at 15:59











  • I think I like the vector of currencies approach best.

    – rogergl
    Nov 26 '18 at 8:07
















3














I suppose this is a matter of semantics. The formal and classical mathematical definition of a Semigroup (A,<>) does requires <> to be a function <>:A×A→A, therefore total. But what is your set A? You need to establish some (naive) set theoretical based semantics for the (Haskell) types and functions you're working with.




  • If the denotation of your types are carrier sets that include as an element, then your Haskell functions will be interpreted as total mathematical functions. In this case you just have to make sure the required laws hold for all elements including . And in your case they do.


  • If instead you consider a model of sets (without ) and partial functions, then to match the classic formal mathematical definition of Semigroup you'd need to make sure <> is total in that setting. And in your case it isn't.



I don't know whether there is a fixed convention. The second, stricter interpretation seems preferable. But the first is a sensible generalisation.



That said have you considered the possibility of using GADTs to distinguish between different currencies at the type level?






share|improve this answer


























  • Well one can add a dollar to a pound, and have a dollar and a pound. (Like a vector space of currencies).

    – n.m.
    Nov 25 '18 at 13:33











  • I don't think including bottom is a useful approach in practice, as it's hard to manipulate diverging computations. Can you write a unit test that verifies bottom <> bottom == bottom?

    – n.m.
    Nov 25 '18 at 15:08











  • You could say the same for any property involving though, including strictness. Furthermore, it's not that simple to avoid . Consider <> defined on function types. The resulting laws establish equalities on (partial) functions. The Semigroup module itself provides the instance Semigroup b => Semigroup (a -> b) where f <> g = x -> f x <> g x.

    – Jorge Adriano
    Nov 25 '18 at 15:39











  • I can, and I usually do ;) One can reason about the bottom, but one cannot work with it. It is not a useful value --- a program that tries to evaluate it is broken. A program can pass unevaluated bottoms around, but since it cannot look at them, one could replace these bottoms by any other value without affecting the meaning of the program.

    – n.m.
    Nov 25 '18 at 15:59











  • I think I like the vector of currencies approach best.

    – rogergl
    Nov 26 '18 at 8:07














3












3








3







I suppose this is a matter of semantics. The formal and classical mathematical definition of a Semigroup (A,<>) does requires <> to be a function <>:A×A→A, therefore total. But what is your set A? You need to establish some (naive) set theoretical based semantics for the (Haskell) types and functions you're working with.




  • If the denotation of your types are carrier sets that include as an element, then your Haskell functions will be interpreted as total mathematical functions. In this case you just have to make sure the required laws hold for all elements including . And in your case they do.


  • If instead you consider a model of sets (without ) and partial functions, then to match the classic formal mathematical definition of Semigroup you'd need to make sure <> is total in that setting. And in your case it isn't.



I don't know whether there is a fixed convention. The second, stricter interpretation seems preferable. But the first is a sensible generalisation.



That said have you considered the possibility of using GADTs to distinguish between different currencies at the type level?






share|improve this answer















I suppose this is a matter of semantics. The formal and classical mathematical definition of a Semigroup (A,<>) does requires <> to be a function <>:A×A→A, therefore total. But what is your set A? You need to establish some (naive) set theoretical based semantics for the (Haskell) types and functions you're working with.




  • If the denotation of your types are carrier sets that include as an element, then your Haskell functions will be interpreted as total mathematical functions. In this case you just have to make sure the required laws hold for all elements including . And in your case they do.


  • If instead you consider a model of sets (without ) and partial functions, then to match the classic formal mathematical definition of Semigroup you'd need to make sure <> is total in that setting. And in your case it isn't.



I don't know whether there is a fixed convention. The second, stricter interpretation seems preferable. But the first is a sensible generalisation.



That said have you considered the possibility of using GADTs to distinguish between different currencies at the type level?







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 25 '18 at 11:29

























answered Nov 25 '18 at 11:21









Jorge AdrianoJorge Adriano

2,220918




2,220918













  • Well one can add a dollar to a pound, and have a dollar and a pound. (Like a vector space of currencies).

    – n.m.
    Nov 25 '18 at 13:33











  • I don't think including bottom is a useful approach in practice, as it's hard to manipulate diverging computations. Can you write a unit test that verifies bottom <> bottom == bottom?

    – n.m.
    Nov 25 '18 at 15:08











  • You could say the same for any property involving though, including strictness. Furthermore, it's not that simple to avoid . Consider <> defined on function types. The resulting laws establish equalities on (partial) functions. The Semigroup module itself provides the instance Semigroup b => Semigroup (a -> b) where f <> g = x -> f x <> g x.

    – Jorge Adriano
    Nov 25 '18 at 15:39











  • I can, and I usually do ;) One can reason about the bottom, but one cannot work with it. It is not a useful value --- a program that tries to evaluate it is broken. A program can pass unevaluated bottoms around, but since it cannot look at them, one could replace these bottoms by any other value without affecting the meaning of the program.

    – n.m.
    Nov 25 '18 at 15:59











  • I think I like the vector of currencies approach best.

    – rogergl
    Nov 26 '18 at 8:07



















  • Well one can add a dollar to a pound, and have a dollar and a pound. (Like a vector space of currencies).

    – n.m.
    Nov 25 '18 at 13:33











  • I don't think including bottom is a useful approach in practice, as it's hard to manipulate diverging computations. Can you write a unit test that verifies bottom <> bottom == bottom?

    – n.m.
    Nov 25 '18 at 15:08











  • You could say the same for any property involving though, including strictness. Furthermore, it's not that simple to avoid . Consider <> defined on function types. The resulting laws establish equalities on (partial) functions. The Semigroup module itself provides the instance Semigroup b => Semigroup (a -> b) where f <> g = x -> f x <> g x.

    – Jorge Adriano
    Nov 25 '18 at 15:39











  • I can, and I usually do ;) One can reason about the bottom, but one cannot work with it. It is not a useful value --- a program that tries to evaluate it is broken. A program can pass unevaluated bottoms around, but since it cannot look at them, one could replace these bottoms by any other value without affecting the meaning of the program.

    – n.m.
    Nov 25 '18 at 15:59











  • I think I like the vector of currencies approach best.

    – rogergl
    Nov 26 '18 at 8:07

















Well one can add a dollar to a pound, and have a dollar and a pound. (Like a vector space of currencies).

– n.m.
Nov 25 '18 at 13:33





Well one can add a dollar to a pound, and have a dollar and a pound. (Like a vector space of currencies).

– n.m.
Nov 25 '18 at 13:33













I don't think including bottom is a useful approach in practice, as it's hard to manipulate diverging computations. Can you write a unit test that verifies bottom <> bottom == bottom?

– n.m.
Nov 25 '18 at 15:08





I don't think including bottom is a useful approach in practice, as it's hard to manipulate diverging computations. Can you write a unit test that verifies bottom <> bottom == bottom?

– n.m.
Nov 25 '18 at 15:08













You could say the same for any property involving though, including strictness. Furthermore, it's not that simple to avoid . Consider <> defined on function types. The resulting laws establish equalities on (partial) functions. The Semigroup module itself provides the instance Semigroup b => Semigroup (a -> b) where f <> g = x -> f x <> g x.

– Jorge Adriano
Nov 25 '18 at 15:39





You could say the same for any property involving though, including strictness. Furthermore, it's not that simple to avoid . Consider <> defined on function types. The resulting laws establish equalities on (partial) functions. The Semigroup module itself provides the instance Semigroup b => Semigroup (a -> b) where f <> g = x -> f x <> g x.

– Jorge Adriano
Nov 25 '18 at 15:39













I can, and I usually do ;) One can reason about the bottom, but one cannot work with it. It is not a useful value --- a program that tries to evaluate it is broken. A program can pass unevaluated bottoms around, but since it cannot look at them, one could replace these bottoms by any other value without affecting the meaning of the program.

– n.m.
Nov 25 '18 at 15:59





I can, and I usually do ;) One can reason about the bottom, but one cannot work with it. It is not a useful value --- a program that tries to evaluate it is broken. A program can pass unevaluated bottoms around, but since it cannot look at them, one could replace these bottoms by any other value without affecting the meaning of the program.

– n.m.
Nov 25 '18 at 15:59













I think I like the vector of currencies approach best.

– rogergl
Nov 26 '18 at 8:07





I think I like the vector of currencies approach best.

– rogergl
Nov 26 '18 at 8:07













2














I don't think it's valid.



Most of the lawful type classes in Haskell (e.g. Semigroup, Monoid, Functor, Monad, etc.) derive their laws from mathematics (e.g. category theory).



Mathematics is based on axioms; that is, assertions about the underlying fabric of numbers, geometry, and similar. By definition, axioms can't be proven, but you usually accept them because they make intuitive sense (e.g. the Peano axioms). In a sense, mathematics is built on a foundation of intuition.



The reason that type classes like the above are lawful is that the laws ensure that the instances behave like you'd expect them to behave.



In Haskell, there's great emphasis on being able to reason about the code, mostly by just looking at the type signatures of functions. One reason you, as a reader, can feel confident about doing this is that whenever a lawful type class is involved, you know that it'll behave in a non-surprising manner.



Most mathematical functions are total (there are exceptions, e.g. division by zero, but exceptions should be drawn from mathematics itself). In light of the above, I'd argue that there's a strong implicit expectation that a type class that derives its laws from mathematics is expected to be total.



The above instance isn't total, which means that it'll behave in a surprising manner for certain inputs. I wouldn't consider it a valid Semigroup instance.






share|improve this answer


























  • Yeah. Division.

    – n.m.
    Nov 25 '18 at 10:56











  • @n.m. What about division?

    – Mark Seemann
    Nov 25 '18 at 10:57






  • 1





    Is it total? What's its domain? To what Haskell type does said domain correspond?

    – n.m.
    Nov 25 '18 at 10:59













  • @n.m. It's not uncommon in mathematics that functions can be "undefined" at points not in its domain. Do we consider the zero denominator part of the division function's domain?

    – Mark Seemann
    Nov 25 '18 at 11:07











  • @n.m. Not that I don't get your point. In Haskell, division is clearly not total, so it does invalidate my argument. Do you, however, find the OP instance valid?

    – Mark Seemann
    Nov 25 '18 at 11:08
















2














I don't think it's valid.



Most of the lawful type classes in Haskell (e.g. Semigroup, Monoid, Functor, Monad, etc.) derive their laws from mathematics (e.g. category theory).



Mathematics is based on axioms; that is, assertions about the underlying fabric of numbers, geometry, and similar. By definition, axioms can't be proven, but you usually accept them because they make intuitive sense (e.g. the Peano axioms). In a sense, mathematics is built on a foundation of intuition.



The reason that type classes like the above are lawful is that the laws ensure that the instances behave like you'd expect them to behave.



In Haskell, there's great emphasis on being able to reason about the code, mostly by just looking at the type signatures of functions. One reason you, as a reader, can feel confident about doing this is that whenever a lawful type class is involved, you know that it'll behave in a non-surprising manner.



Most mathematical functions are total (there are exceptions, e.g. division by zero, but exceptions should be drawn from mathematics itself). In light of the above, I'd argue that there's a strong implicit expectation that a type class that derives its laws from mathematics is expected to be total.



The above instance isn't total, which means that it'll behave in a surprising manner for certain inputs. I wouldn't consider it a valid Semigroup instance.






share|improve this answer


























  • Yeah. Division.

    – n.m.
    Nov 25 '18 at 10:56











  • @n.m. What about division?

    – Mark Seemann
    Nov 25 '18 at 10:57






  • 1





    Is it total? What's its domain? To what Haskell type does said domain correspond?

    – n.m.
    Nov 25 '18 at 10:59













  • @n.m. It's not uncommon in mathematics that functions can be "undefined" at points not in its domain. Do we consider the zero denominator part of the division function's domain?

    – Mark Seemann
    Nov 25 '18 at 11:07











  • @n.m. Not that I don't get your point. In Haskell, division is clearly not total, so it does invalidate my argument. Do you, however, find the OP instance valid?

    – Mark Seemann
    Nov 25 '18 at 11:08














2












2








2







I don't think it's valid.



Most of the lawful type classes in Haskell (e.g. Semigroup, Monoid, Functor, Monad, etc.) derive their laws from mathematics (e.g. category theory).



Mathematics is based on axioms; that is, assertions about the underlying fabric of numbers, geometry, and similar. By definition, axioms can't be proven, but you usually accept them because they make intuitive sense (e.g. the Peano axioms). In a sense, mathematics is built on a foundation of intuition.



The reason that type classes like the above are lawful is that the laws ensure that the instances behave like you'd expect them to behave.



In Haskell, there's great emphasis on being able to reason about the code, mostly by just looking at the type signatures of functions. One reason you, as a reader, can feel confident about doing this is that whenever a lawful type class is involved, you know that it'll behave in a non-surprising manner.



Most mathematical functions are total (there are exceptions, e.g. division by zero, but exceptions should be drawn from mathematics itself). In light of the above, I'd argue that there's a strong implicit expectation that a type class that derives its laws from mathematics is expected to be total.



The above instance isn't total, which means that it'll behave in a surprising manner for certain inputs. I wouldn't consider it a valid Semigroup instance.






share|improve this answer















I don't think it's valid.



Most of the lawful type classes in Haskell (e.g. Semigroup, Monoid, Functor, Monad, etc.) derive their laws from mathematics (e.g. category theory).



Mathematics is based on axioms; that is, assertions about the underlying fabric of numbers, geometry, and similar. By definition, axioms can't be proven, but you usually accept them because they make intuitive sense (e.g. the Peano axioms). In a sense, mathematics is built on a foundation of intuition.



The reason that type classes like the above are lawful is that the laws ensure that the instances behave like you'd expect them to behave.



In Haskell, there's great emphasis on being able to reason about the code, mostly by just looking at the type signatures of functions. One reason you, as a reader, can feel confident about doing this is that whenever a lawful type class is involved, you know that it'll behave in a non-surprising manner.



Most mathematical functions are total (there are exceptions, e.g. division by zero, but exceptions should be drawn from mathematics itself). In light of the above, I'd argue that there's a strong implicit expectation that a type class that derives its laws from mathematics is expected to be total.



The above instance isn't total, which means that it'll behave in a surprising manner for certain inputs. I wouldn't consider it a valid Semigroup instance.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 25 '18 at 11:26

























answered Nov 25 '18 at 10:53









Mark SeemannMark Seemann

183k33325559




183k33325559













  • Yeah. Division.

    – n.m.
    Nov 25 '18 at 10:56











  • @n.m. What about division?

    – Mark Seemann
    Nov 25 '18 at 10:57






  • 1





    Is it total? What's its domain? To what Haskell type does said domain correspond?

    – n.m.
    Nov 25 '18 at 10:59













  • @n.m. It's not uncommon in mathematics that functions can be "undefined" at points not in its domain. Do we consider the zero denominator part of the division function's domain?

    – Mark Seemann
    Nov 25 '18 at 11:07











  • @n.m. Not that I don't get your point. In Haskell, division is clearly not total, so it does invalidate my argument. Do you, however, find the OP instance valid?

    – Mark Seemann
    Nov 25 '18 at 11:08



















  • Yeah. Division.

    – n.m.
    Nov 25 '18 at 10:56











  • @n.m. What about division?

    – Mark Seemann
    Nov 25 '18 at 10:57






  • 1





    Is it total? What's its domain? To what Haskell type does said domain correspond?

    – n.m.
    Nov 25 '18 at 10:59













  • @n.m. It's not uncommon in mathematics that functions can be "undefined" at points not in its domain. Do we consider the zero denominator part of the division function's domain?

    – Mark Seemann
    Nov 25 '18 at 11:07











  • @n.m. Not that I don't get your point. In Haskell, division is clearly not total, so it does invalidate my argument. Do you, however, find the OP instance valid?

    – Mark Seemann
    Nov 25 '18 at 11:08

















Yeah. Division.

– n.m.
Nov 25 '18 at 10:56





Yeah. Division.

– n.m.
Nov 25 '18 at 10:56













@n.m. What about division?

– Mark Seemann
Nov 25 '18 at 10:57





@n.m. What about division?

– Mark Seemann
Nov 25 '18 at 10:57




1




1





Is it total? What's its domain? To what Haskell type does said domain correspond?

– n.m.
Nov 25 '18 at 10:59







Is it total? What's its domain? To what Haskell type does said domain correspond?

– n.m.
Nov 25 '18 at 10:59















@n.m. It's not uncommon in mathematics that functions can be "undefined" at points not in its domain. Do we consider the zero denominator part of the division function's domain?

– Mark Seemann
Nov 25 '18 at 11:07





@n.m. It's not uncommon in mathematics that functions can be "undefined" at points not in its domain. Do we consider the zero denominator part of the division function's domain?

– Mark Seemann
Nov 25 '18 at 11:07













@n.m. Not that I don't get your point. In Haskell, division is clearly not total, so it does invalidate my argument. Do you, however, find the OP instance valid?

– Mark Seemann
Nov 25 '18 at 11:08





@n.m. Not that I don't get your point. In Haskell, division is clearly not total, so it does invalidate my argument. Do you, however, find the OP instance valid?

– Mark Seemann
Nov 25 '18 at 11:08


















draft saved

draft discarded




















































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.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53466359%2fmust-the-operator-for-a-semigroup-be-defined-for-all-arguments%23new-answer', 'question_page');
}
);

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







Popular posts from this blog

A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

Calculate evaluation metrics using cross_val_predict sklearn

Insert data from modal to MySQL (multiple modal on website)