Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-composability of GI.PangoCairo.fontMapGetDefault and GI.PangoCairo.fontMapGetResolution. #77

Closed
deepfire opened this issue Feb 24, 2017 · 5 comments

Comments

@deepfire
Copy link

According to https://hackage.haskell.org/package/gi-pangocairo-1.0.11/docs/src/GI-PangoCairo-Interfaces-FontMap.html#fontMapGetDefault :

fontMapGetDefault ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    m Pango.FontMap.FontMap

..and..

fontMapGetResolution ::
    (B.CallStack.HasCallStack, MonadIO m, IsFontMap a) =>
    a
    {- ^ /@fontmap@/: a 'GI.PangoCairo.Interfaces.FontMap.FontMap' -}
    -> m Double
    {- ^ __Returns:__ the resolution in \"dots per inch\" -}

..which, in absence of some kind of hard-to-figure-out casting, makes these functions non-composable.

@deepfire deepfire changed the title Non-composabilitu of GI.PangoCairo.fontMapGetDefault and GI.PangoCairo.fontMapGetResolution. Non-composability of GI.PangoCairo.fontMapGetDefault and GI.PangoCairo.fontMapGetResolution. Feb 24, 2017
@deepfire
Copy link
Author

Exhibit:

 GIPC.fontMapGetResolution =<< GIPC.fontMapGetDefault

<interactive>:36:1: error:
     Required ancestor GIPC.FontMap not found for type GIP.FontMap’.
     In the first argument of (=<<), namely
        GIPC.fontMapGetResolution
      In the expression:
        GIPC.fontMapGetResolution =<< GIPC.fontMapGetDefault
      In an equation for it’:
          it = GIPC.fontMapGetResolution =<< GIPC.fontMapGetDefault

@garetxe
Copy link
Collaborator

garetxe commented Feb 25, 2017

Thanks for the report.

As far as I can tell the issue here is with the design of the original API, the generated bindings are accurate. The problem is that there are two closely related types: Pango.FontMap and PangoCairo.FontMap. Every PangoCairo.FontMap is a Pango.FontMap, but not necessarily the other way round.

fontMapGetDefault returns a Pango.FontMap, and since this is not necessarily a PangoCairo.FontMap, the type system cannot ensure that the cast is safe, so you need to do it at runtime (admittedly the error message could hint that you may want to use a runtime cast, this may be a good thing to add). The following works, for example:

λ> import qualified GI.PangoCairo as PC
λ> import Data.GI.Base (unsafeCastTo)
λ> PC.fontMapGetDefault >>= unsafeCastTo PC.FontMap >>= PC.fontMapGetResolution
96.0

I am using unsafeCastTo here for conciseness, but if you can sensibly deal with the error case in your code, you may want to use castTo instead.

@deepfire
Copy link
Author

I don't think this is the entire information -- quoting the documentation:

PangoFontMap * pango_cairo_font_map_get_default (void);

Gets a default PangoCairoFontMap to use with Cairo.

..so while the source code might only be returning a generic PangoFontMap, the documentation says it's a specific PangoCairoFontMap.

So, there goes. And, actually, I doubt it's the only case in the API, where the documentation is more precise than the C-level types.

And, given C's limitations, I guess we can all see the reason why the API providers are using the least common denominator..

@garetxe
Copy link
Collaborator

garetxe commented Feb 25, 2017

Looking to the relevant pangocairo source, it is clear that you are completely right. The API is intended to return a PangoCairo.FontMap. The issue is that the relevant methods (new, newFromFont and getDefault) are not marked as constructors in the introspection data. I added an override fixing this in 5492e21, and released gi-pangocairo-1.0.12 to hackage with the fix.

Thanks again for the report!

@deepfire
Copy link
Author

Thank you a lot, once again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants