Say I have a class
class T where
tag1 :: String
tag2 :: String
With ambiguous types enabled, I could specify each of them in an instance:
instance T A where
tag1 = "tag1"
tag2 = "tag2"
If I want to make tag2 append something to tag1, I can define
instance T A where
tag1 = "tag1"
tag2 = tag1 @A ++ " suffix"
This works great, but if I want tag2 to always append suffix to each tag1, I seem to have to specify the ambiguous call for each instance.
I understand the need for this, as tag1 from any instance would work for each call. However, is there any trick within haskell for me to specify it once only?
Something like
tag2 :: T a => String
tag2 = tag1 @a ++ " suffix"
Your code currently does not compile since the type class has no type parameters, so I'm going to assume your code is actually (assuming AllowAmbiguousTypes is enabled)
class T a where
tag1 :: String
tag2 :: String
Now you can provide a default implementation for tag2:
class T a where
tag1 :: String
tag2 :: String
tag2 = "tag2"
But this does not meet the requirement of adding the suffix to tag1.
We could try this(assuming TypeApplications is enabled):
class T a where
tag1 :: String
tag2 :: String
tag2 = tag1 @a ++ "suffix"
Now this won't compile, and the compilation error will be
error: Not in scope: type variable `a'
and rightfully so, the type a isn't defined anywhere. However, we want to refer to the a in the head of the class, for this we need the language extension ScopedTypeVariables, and with that the code will compile and you'll get the results you expect (I suggest reading up the linked documentation)
Here's a full program that demonstrates the usage:
{-# LANGUAGE TypeApplications, AllowAmbiguousTypes, ScopedTypeVariables #-}
class T a where
tag1 :: String
tag2 :: String
tag2 = tag1 @a ++ " suffix"
data A = A
data B = B
instance T A where
tag1 = "tagA"
instance T B where
tag1 = "tagB"
tag2 = "tagB overriden"
main = do
putStrLn $ tag1 @A
putStrLn $ tag2 @A
putStrLn $ tag1 @B
putStrLn $ tag2 @B
And the output is:
> ./foo
tagA
tagA suffix
tagB
tagB overriden
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