I am learning haskell and am having trouble following the line of thought. I am trying to think in C++ terms and I am unable to find the equivalent of C++ subclass in Haskell. How do I say data B is also data A for simple structs A and B?
Background: I have read LearnYouAHaskell at least thrice. I am able to write basic Haskell code, but nothing very advanced and am fairly experienced working in C++.
Attempts: I was trying to think in terms of defining A as a type class and making B an instance of A. However, I don't want to write new definition of the method/data member and just want to use the definition of A. I am unable to comprehend the error messages.
-- Trial.hs
class A a where
data_member :: Int
data B = B {
x :: Int
}
instance A B;
Trial.hs:2:9: error:
• Could not deduce (A a0)
from the context: A a
bound by the type signature for:
data_member :: A a => Int
at Trial.hs:2:9-26
The type variable ‘a0’ is ambiguous
• In the ambiguity check for ‘data_member’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the class method: data_member :: forall a. A a => Int
In the class declaration for ‘A’
Like Damian suggests, use a Sum type: The |
type operator/constructor.
Using ADT (Algebraic Data Types) is a great strength of Haskell. Dive blindlessly into using them whenever you can, I think all programmer learning haskell with an Imperative background come to this same conclusion: ADT are incredibly useful and concise.
Coming from a C++ background, when I first groked the Sum type I was translating it to C++ in my mind this way:
data PureVirtualClassA = ConcreteClassB Member1 Member2 | ConcreteClassC Member3
where Member1, Member2, and Member3 would be the types of a struct member. You can simplify this example with all the three being Int:
data PureVirtualClassA = ConcreteClassB Int Int | ConcreteClassC Int
(If you want a named data member, you should go for using Records, but they are not always needed)
Now you can use it in a function, just like you would use C++ polymorphism, where ConcreteClassB and ConcreteClassC would be deriving from PureVirtualClassA:
myFunction :: PureVirtualClassA -> Int
myFunction (ConcreteClassB x y) = x + y
myFunction (ConcreteClassC z) = z
IMPORTANT NOTE: In those examples for the C++ programmer I have used the word Class with the C++ meaning! Don't use the word Class this way in Haskell. A class in Haskell is something different, it's more like an interface, but the comparison does not stand.
You can create a new type containing both:
data A = A Int
data B = B Int
data AB = MakeA A | MakeB B
:t MakeA $ A 4
MakeA $ A 4 :: AB
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With