[GHC] #8538: confusing specialization CORE warning, also can't mark type class instances INLINEABLE unless class defn is marked INLINEABLE

GHC ghc-devs at haskell.org
Sun Nov 17 23:42:31 UTC 2013


#8538: confusing specialization CORE warning, also  can't mark type class
instances INLINEABLE unless class defn is marked INLINEABLE
------------------------------------+-------------------------------------
       Reporter:  carter            |             Owner:
           Type:  bug               |            Status:  new
       Priority:  normal            |         Milestone:
      Component:  Compiler          |           Version:  7.6.3
       Keywords:                    |  Operating System:  Unknown/Multiple
   Architecture:  Unknown/Multiple  |   Type of failure:  None/Unknown
     Difficulty:  Unknown           |         Test Case:
     Blocked By:                    |          Blocking:
Related Tickets:                    |
------------------------------------+-------------------------------------
 As part of writing an array library for numerical purposes, I have a
 static sized strict list type for representing the Indexing tuple. One
 implementation strategy makes it a tad generic, and then I'm writing a
 bunch of manipulation utilities using Functor, Applicative and Foldable.

 I wrote it with all the functions marked INLINABLE so i could ensure that
 I could have the index arith calculations SPECIALIZE in the common cases.

 Unfortunately, it seems like type class instances can only marked
 INLINABLE  if the type class definition is itself marked INLINE or
 INLINABLE. Considering i'm writing a numerical array library, I want to
 make sure that address arithmetic.

 This could could be argued to be by design (and thus a wont fix).

 That aside, I also get the following Warning for my "map2" function, which
 i found surprising. (and it perhaps is worth some investigation / cleanup
 )

 {{{

 src/Numerical/Types/Shape.hs:165:1: Warning:
     RULE left-hand side too complicated to desugar
       let {
         $dFunctor :: Functor (Shape ('S N0))
         [LclId]
         $dFunctor =
           Numerical.Types.Shape.$fFunctorShape @ 'Z $dFunctor } in
       map2
         @ a
         @ b
         @ c
         @ N2
         (Numerical.Types.Shape.$fApplicativeShape
            @ ('S N0)
            (Numerical.Types.Shape.$fFunctorShape @ ('S N0) $dFunctor)
            (Numerical.Types.Shape.$fApplicativeShape
               @ 'Z $dFunctor Numerical.Types.Shape.$fApplicativeShape0))
 }}}


 {{{
 {-# LANGUAGE PolyKinds   #-}
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE NoImplicitPrelude #-}

 module Numerical.Types.Shape where

 import GHC.Magic
 import Data.Monoid
 import Data.Functor
 import Data.Foldable
 import Control.Applicative

 -- import Numerical.Types.Nat

 import Prelude (seq, ($!),($),Show(..),Eq(),Int)

 data Nat = S !Nat  | Z

 type N0 = Z

 type N1= S N0

 type N2 = S N1

 type N3 = S N2

 type N4 = S N3

 {-
 not doing the  HLIST style shape because I don't want to have
 any pattern matchings going on.

 Also would play hell with locality quality in the address translation
 hackery,
 because there'd be an extra load to get those ints!
 -}
 infixr 3 :*

  {-
 the concern basically boils down to "will it specialize / inline well"

  -}
 data Shape (rank :: Nat) a where
     Nil  :: Shape Z a
     (:*) ::  !(a) -> !(Shape r a ) -> Shape  (S r) a

 --deriving instance (Show (Shape rank a))

     -- deriving instance Eq (Shape rank a)


     -- #if defined( __GLASGOW_HASKELL__ ) &&  ( __GLASGOW_HASKELL__  >=
 707)
     --deriving instance Typeable (Shape rank a)
     -- #endif



 instance Functor (Shape Z) where

     fmap  = \ f Nil -> Nil
     {-# INLINABLE fmap #-}

 {-# SPECIALIZE fmap :: (a ->b  )-> (Shape Z a)-> (Shape Z b) #-}

 instance  (Functor (Shape r)) => Functor (Shape (S r)) where

     fmap  = \ f (a :* rest) -> f a :* fmap f rest
     {-# INLINABLE fmap  #-}

 {-# SPECIALIZE fmap :: (a ->b )-> (Shape N1 a)-> (Shape N1 b) #-}
 {-# SPECIALIZE fmap :: (a ->b )-> (Shape N2 a)-> (Shape N2 b) #-}

 instance  Applicative (Shape Z) where
     pure = \ _ -> Nil
     {-# INLINE pure #-}

     (<*>) = \ _  _ -> Nil
     {-# INLINE (<*>) #-}

 {-# SPECIALIZE pure  :: a -> Shape Z a #-}
 {-# SPECIALIZE (<*>) ::  Shape Z (a -> b) -> Shape Z a -> Shape Z b #-}

 instance  Applicative (Shape r)=> Applicative (Shape (S r)) where
     pure = \ a -> a :* (pure a)
     {-# INLINE pure  #-}

     (<*>) = \ (f:* fs) (a :* as) ->  f a :* (inline (<*>)) fs as
     {-# INLINE (<*>) #-}

 {-# SPECIALIZE pure :: a -> (Shape Z  a) #-}
 {-# SPECIALIZE pure :: a -> (Shape N1 a) #-}
 {-# SPECIALIZE pure :: a -> (Shape N2 a )#-}

 instance Foldable (Shape Z) where
     foldMap = \ _ _ -> mempty
     {-# INLINE foldMap #-}

     foldl = \ _ init  _ -> init
     {-# INLINE foldl #-}

     foldr = \ _ init _ -> init
     {-# INLINE foldr #-}

     foldr' = \_ !init _ -> init
     {-# INLINE foldr' #-}

     foldl' = \_ !init _ -> init
     {-# INLINE foldl' #-}

 --    {-# SPECIALIZE foldMap :: Monoid m => (a -> m)-> Shape Z a -> m  #-}
 --    {-# SPECIALIZE foldl :: (a ->b -> a) -> a -> Shape Z b -> a  #-}
 --    {-# SPECIALIZE foldr :: (b ->a -> a) -> a -> Shape Z b -> a  #-}
 --    {-# SPECIALIZE foldl' :: (a ->b -> a) -> a -> Shape Z b -> a  #-}
 --    {-# SPECIALIZE foldr' :: (b ->a -> a) -> a -> Shape Z b -> a  #-}


 instance (Foldable (Shape r))  => Foldable (Shape (S r)) where
     foldMap = \f  (a:* as) -> f a <> foldMap f as
     {-# INLINE foldMap #-}

     foldl' = \f !init (a :* as) -> let   next = f  init a   in     next
 `seq` (inline foldl) f next as
     {-# INLINE foldl' #-}

     foldr' = \f !init (a :* as ) -> f a $! (inline foldr) f init as
     {-# INLINABLE foldr' #-}

     foldl = \f init (a :* as) -> let   next = f  init a  in   (inline
 foldl) f next as
     {-# INLINE foldl #-}

     foldr = \f init (a :* as ) -> f a $ (inline foldr) f init as
     {-# INLINE foldr  #-}

 {-# SPECIALIZE foldMap::Monoid m => (a -> m)-> Shape N1 a -> m  #-}
 {-# SPECIALIZE foldl :: (a ->b -> a) ->a -> Shape N1 b -> a  #-}
 {-# SPECIALIZE foldr :: (b ->a -> a) -> a -> Shape N1 b  -> a  #-}
 {-# SPECIALIZE foldl' :: (a ->b -> a) -> a -> Shape N1 b -> a  #-}
 {-# SPECIALIZE foldr' :: (b ->a -> a) -> a -> Shape N1 b -> a  #-}

 {-# SPECIALIZE foldMap :: Monoid m => (a -> m)-> Shape N2 a -> m  #-}
 {-# SPECIALIZE foldl :: (a ->b-> a) ->a -> Shape N2 b -> a  #-}
 {-# SPECIALIZE foldr :: (b ->a -> a) -> a -> Shape N2 b -> a  #-}
 {-# SPECIALIZE foldl' :: (a ->b -> a) -> a -> Shape N2 b -> a  #-}
 {-# SPECIALIZE foldr' :: (b ->a -> a) -> a -> Shape N2 b -> a  #-}

 --
 map2 :: (Applicative (Shape r))=> (a->b ->c) -> (Shape r a) -> (Shape r b)
 -> (Shape r c )
 map2 = \f l r -> pure f <*>  l  <*> r

 {-# INLINABLE map2 #-}

 {-# SPECIALIZE map2 :: (a -> b -> c ) -> (Shape  Z a) -> (Shape  Z b) ->
 (Shape Z c )#-}
 {-# SPECIALIZE map2 :: (a -> b -> c ) -> (Shape  N1 a) -> (Shape  N1 b) ->
 (Shape  N1 c )#-}
 {-# SPECIALIZE map2 :: (a -> b -> c ) -> (Shape N2 a) -> (Shape  N2 b) ->
 (Shape  N2  c )#-}


 }}}

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8538>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list