Background: I am working on a declarative compiler. In this course, I am going to write a class to construct an intermediate data structure. After building the data structure, the output can be redendered from the data structure. To simplify for stackoverflow, I created the following code:
module Main where
import qualified Data.Word as W
import qualified Octetable as Oct
main :: IO ()
main =
do
print (buildNRender "123")
data MyData = MyData Integer
data Construction model = Contains model | Error String
deriving Show
class Builder g where
build :: String -> (Construction g)
render :: (Construction g) -> [W.Word8]
buildNRender :: String -> [W.Word8]
buildNRender = render . build
instance Builder MyData where
build s = Contains (MyData (read s :: Integer))
render (Contains (MyData n)) = Oct.toOctets n
render (Error _) = []
The obvious problem is, 'buildNRender' cannot be part of Builder, because type parameter g is not used at all.
Now, it seems obvious to me that a type class cannot work like this, where an intermediate value in a combination of two or more functions has a type parameter.
The following code makes the intermediate type explicit, and works - but without buildNRender.
...
main :: IO ()
main =
do
print (render ((build "123") :: (Construction MyData))
...
However, is there an elegant way to define such a DEFAULT method of a class (like 'buildNRender'), and to specify the intermediate type in the context of the caller, like in the following code?
...
main :: IO ()
main =
do
print ((buildNRender "123") :: ?(Construction MyData)?)
...