[GHC] #12363: Type application for infix

GHC ghc-devs at haskell.org
Tue Jan 10 13:17:51 UTC 2017


#12363: Type application for infix
-------------------------------------+-------------------------------------
        Reporter:  Iceland_jack      |                Owner:
            Type:  feature request   |               Status:  new
        Priority:  lowest            |            Milestone:
       Component:  Compiler          |              Version:  8.0.1
  (Parser)                           |             Keywords:
      Resolution:                    |  TypeApplications
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by Iceland_jack):

 Replying to [comment:15 rwbarton]:
 > I don't know if it's the sheer number of updates to this ticket, but
 this syntax is starting to look fairly natural to me.

 Just According to Keikaku.⁽¹⁾

 ⁽¹⁾
 [https://www.reddit.com/r/OutOfTheLoop/comments/467byi/what_the_hell_is_keikaku/
 (Translator's note: keikaku means plan)]

 > Most of these examples don't look like code I would ever write, but the
 {{{`catch` @IOException}}} example is pretty sweet.

 It works especially well with operators where the specified type does not
 appear in the return type: having to privilege one side over the other
 feels asymmetric, the [https://hackage.haskell.org/package/intervals
 intervals] package documentation gives a lot of good examples where this
 is useful:

 {{{#!hs
 -- >>> (5 ... 10 :: Interval Double) <! (20 ... 30 :: Interval Double)
 -- True
 >>> (5 ... 0) <! @Double (20 ... 30)
 True

 -- >>> (20 ... 40 :: Interval Double) `contains` (15 ... 35 :: Interval
 Double)
 -- False
 >>> (20 ... 40) `contains` @Double (15 ... 35)
 False
 }}}

 but also simpler examples, I will avoid writing an explicit annotation if
 I can

 {{{#!hs
 -- >>> (0.1 :: Float) + 0.2 == 0.3
 -- True
 >>> 0.1 + 0.2 == @Float  0.3
 True

 -- >>> 0.1 + 0.2 == (0.3 :: Double)
 -- False
 >>> 0.1 + 0.2 == @Double 0.3
 False

 -- >>> 0 `elem` [1,2::Int,3]
 -- False
 >>> 0 `elem` @[] @Int [1,2,3]
 False
 }}}

 For most examples you can easily annotate some other part of the
 expression to get the same effect. My experience is that infix type
 application leads to less thinking, more consistency (in where the type
 goes) and more resistance to change: I prefer the uncommented versions

 {{{#!hs
 -- n `hashWithSalt` (fromIntegral (ptrToIntPtr s) :: Int)
 -- n `hashWithSalt` fromIntegral @_ @Int (ptrToIntPtr s)
 n `hashWithSalt` @Int fromIntegral (ptrToIntPtr s)
 }}}

 {{{#!hs
 -- Var a             -> digest c (1 :: Word8) `digest` a
 -- App f x           -> digest c (2 :: Word8) `digest` f `digest` x
 -- HardType h        -> digest c (3 :: Word8) `digest` h
 -- Forall k tvs cs b -> digest c (4 :: Word8) `digest` k `digest` tvs
 `digest` cs `digest` b
 -- Loc _ ty          -> digest c ty
 -- Exists k tvs cs   -> digest c (5 :: Word8) `digest` k `digest` tvs
 `digest` cs
 -- And xs            -> digest c (6 :: Word8) `digest` xs
 Var a             -> c `digest` @Word8 1 `digest` a
 App f x           -> c `digest` @Word8 2 `digest` f `digest` x
 HardType h        -> c `digest` @Word8 3 `digest` h
 Forall k tvs cs b -> c `digest` @Word8 4 `digest` k `digest` tvs `digest`
 cs `digest` b
 Loc _ ty          -> c `digest` ty
 Exists k tvs cs   -> c `digest` @Word8 5 `digest` k `digest` tvs `digest`
 cs
 And xs            -> c `digest` @Word8 6 `digest` xs
 }}}

 and

 {{{#!hs
 -- tAG_BITS_MAX = (1 `shiftL` tAG_BITS) :: Int
 tAG_BITS_MAX = 1 `shiftL` @Int tAG_BITS
 }}}

 ----

 I would still say the main usefulness is pedagogy: I will not introduce
 invalid syntax when explaining things to newcomers, but for questions like
 [https://www.reddit.com/r/haskellquestions/comments/5mtk8v/instance_eq_question/
 this]

 {{{#!hs
   Nodo x ys zs == Nodo x' ys' zs' = x == x' && ys == ys' && zs == zs'
 }}}

 maybe it would help to write it like this, to show the different
 instantiations of `==`

 {{{#!hs
   Nodo x ys zs == Nodo x' ys' zs' =

        x  == @a        x'
     && ys == @(Heap a) ys'
     && zs == @(Heap a) zs'
 }}}

 In the end it's up to what the community thinks

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


More information about the ghc-tickets mailing list