Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a typeclass in haskell for boolean values?

I am trying to learn some Haskell by looking at a superb short and educational article on comonad application from 2006 link and it contains an expression like rule (U (a:_) b (c:_)) = not (a && b && not c || (a==b)) whre U is a zipper comonad. That is stated in data U x = [x] x [x] and accompanying implementations of the comonad operations.

Trying to learn more, I am attempting to annotate the type of the expression manually. A wise choice seems to be rule :: U Bool -> Bool, but that seems a bit... restrictive. I could imagine other types that would be able to have truthyness values, such as Ints (0 corresponds to false, all other values could be True) and other.

If there was a type class for truthyness called truthy, I guess I could write rule :: (Truthy t) => U t -> Bool. Since I want to iterate over rule, the first type annotation (rule :: U Bool -> Bool) is good enough, but still the question tickles my brain.

Is there such a typeclass? If there is, what is it called? If not, why is there no need for it?

like image 420
LudvigH Avatar asked Jul 04 '17 19:07

LudvigH


People also ask

What is Typeclass in Haskell?

What's a typeclass in Haskell? A typeclass defines a set of methods that is shared across multiple types. For a type to belong to a typeclass, it needs to implement the methods of that typeclass. These implementations are ad-hoc: methods can have different implementations for different types.

Are there classes in Haskell?

Haskell classes are roughly similar to a Java interface. Like an interface declaration, a Haskell class declaration defines a protocol for using an object rather than defining an object itself.

What does deriving show mean Haskell?

Deriving means that your data type is automatically able to "derive" instances for certain type classes. In this case BaseballPlayer derives Show which means we can use any function that requires an instance of Show to work with BaseballPlayer .

What is an instance in Haskell?

An instance of a class is an individual object which belongs to that class. In Haskell, the class system is (roughly speaking) a way to group similar types. (This is the reason we call them "type classes"). An instance of a class is an individual type which belongs to that class.


1 Answers

Digression: Generally we don't use type classes to do what you might call mere overloading, of the sort you find in dynamic languages (e.g. making + mean "concatenate lists" or "add ints", or overloading boolean operations to work on "truthy" values as in your question). The difference is I guess that we say good abstractions are made with type classes that have a set of laws that hold them together, so that you can write polymorphic code that is useful. It might be that we can make a "truthy" class that's good by this standard but I'm not sure.

But to get to your question, there are certainly classes that abstract boolean logic to some degree (the field of study here being maybe Boolean algebra), the most relevant here probably being the Bits class from Data.Bits.

So you'd get:

-- note, the polymorphic `t` has cooties, and we'd need to be able to
-- make the caller polymorphic in a sensible way too for this to make sense
rule :: (Bits t) => U t -> t
rule (U (a:_) b (c:_)) = complement (a .&. b .&. complement c .|. complement (a `xor` b))

The only tricky bit above is a == b becomes the wordy more general form complement (a ``xor`` b). Actually if we restrict ourselves to the fundamental operations (AND/OR/NOT), then the more general form of == is quite complicated:

a .==. b = complement ((a .|. b) .&. complement (a .&. b))

It would be interesting to see whether or in what way this operation makes sense with this more general type (I don't know what it's meant to do), e.g. does it do something sensible for Int. Then compare that with Int had we used your "truthy" class. Is one more useful than the other? Does the Bits version give you any new insight into the algorithm or is it just an arbitrary overloading?

Edit: here's something interesting about working in this more abstract domain: we can use the laws of boolean algebra to reduce and understand our expression better. For instance by handing it off to Wolfram Alpha we can observe that the normalized forms of our expression don't contain c at all (you should double-check I haven't made a mistake somewhere), so we might as well have written:

rule (U (a:_) b _) = (a && not b) || (not a && b)

This might be interesting insight (is that c even necessary in our data structure?) or might indicate a bug in our logic.

like image 127
jberryman Avatar answered Nov 15 '22 03:11

jberryman