Custom typeclass instance
I have a data type Book that is an instance of custom typeclass Printable that has a function print. The print function returns Text that I want to print using debug statement. However, I am not able to print it directly with
debug $ print myBook -- this gives error
But if I first assign the function’s return value to a variable and then use debug, it works.
printOut: Text = print myBook
debug printOut -- this works
Can you please suggest what could be the issue here, and why do I need to assign it to a variable before printing?
Here is the full code and the error statement:
data Book = Book with
title: Text
author: Text
class Printable i o where
print: i -> o
instance Printable Book Text where
print aBook = "Title: " <> aBook.title <> " by " <> aBook.author
testPrintable = script do
let
myBook = Book with
title = "Learn you a Daml"
author = "Digital Asset"
printOut: Text = print myBook
--debug $ print myBook -- this gives error
debug printOut -- this works
return()
The error message:
• Ambiguous type variable ‘b0’ arising from a use of ‘debug’
prevents the constraint ‘(Show b0)’ from being solved.
Probable fix: use a type annotation to specify what ‘b0’ should be.
These potential instances exist:
instance (Show a, Show b) => Show (Either a b)
-- Defined in ‘GHC.Show’
instance Show BigNumeric -- Defined in ‘GHC.Show’
instance Show (Numeric n) -- Defined in ‘GHC.Show’
...plus 30 others
...plus six instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of a 'do' block: debug $ print myBook
In the first argument of ‘script’, namely
‘do let myBook = ...
let printOut : Text = print myBook
debug $ print myBook
debug printOut
....’
In the expression:
script
do let myBook = ...
let printOut : Text = print myBook
debug $ print myBook
debug printOut
....typecheck
Essentially, you have the problem with multi-parameter typeclasses described here; where the ambiguous variable in that article is m, you have o being ambiguous.
debug does not sufficiently constrain o; consider its signature.
The standard solution is exactly the one in the followup article, a “functional dependency” or “fundep”. However, keep in mind that this is dependent [sorry] on your specific typeclass semantics, i.e. using a fundep here will make it so each choice of i can have one and only one Printable, not a bunch with different o choices. (That is, after all, the promise you are making when you declare the fundep “o is determined by i”.)
Fundeps are commonly used in the Daml standard library, e.g. HasExercise.
Thanks @Stephen !
So is it correct to say that the problem is with the debug function and not the way I have defined the Printable type-class? I am not sure how I can ‘constrain’ o in its definition.
Note: my conclusion above is based on just your response. I will read up the articles you linked later as they look like some heavy-lifting!
@Neelam_Dwivedi
Here’s how you can do it
class Printable i o | i -> o where
print: i -> o
Thanks @a_putkov ![]()