How do the operators `>>>` and `>>=` work in Haskell?

I have been reading through a Haskell d3js library:

This is the code defining Haskell box:

box :: Selector ->  (Double,Double) -> St (Var' Selection)
box parent (w,h) = do
    assign
        $ ((d3Root
            >>> select parent
            >>> func "append" [PText "svg"]
            >>> width w
            >>> height h
            >>> style "background" "#eef") :: Chain () Selection)

The code actually exporting using the box function in d3.js code uses the >>= operator like this:

import Control.Monad
import qualified Data.Text as T
import D3JS

test :: Int -> IO ()
test n = T.writeFile "generated.js" $ reify (box "#div1" (300,300) >>= bars n 300 (Data1D [100,20,80,60,120]))

To avoid being like this unpopular question on arrows: How to use arrow operators in haskell Where can I find the type signatures, or other basic information? Are there resources where I can learn more about:

  • $ Haskell: difference between . (dot) and $ (dollar sign)
  • >>> this could be an arrow but I don't see where I imported it.
  • >>=
  • The first one was easy to find but the answer was confusing:

    *Main Lib> :t ($)
    ($) :: (a -> b) -> a -> b
    

    I found that f $ abc = f ( (ab) c ) while fabc = (((fa) b) c

    Prelude gives a similar response for >>= involving monads. In my case, it might be the IO monad. Or the d3js statement monad St()

    *Main Lib> :t (>>=)
    (>>=) :: Monad m => m a -> (a -> m b) -> m b
    

    The last one doesn't show up at all... which is too bad because it looks pretty essential

    *Main Lib> :t (>>>)
    
    <interactive>:1:1:
        Not in scope: ‘>>>’
        Perhaps you meant one of these:
          ‘>>’ (imported from Prelude), ‘>>=’ (imported from Prelude)
    

    Lastly at the risk of bundling too many questions at once. Can someone explain this type signature? Especially the last item:

    box :: Selector ->  (Double,Double) -> St (Var' Selection)
    

    The package Index

    Packages on Hackage usually have an index page of all functions / types / etc. defined. The index for the d3js package is located here:

  • https://hackage.haskell.org/package/d3js-0.1.0.0/docs/doc-index.html
  • You can get there by:

  • Visit the front page for the package
  • Click on any module name in the exported module tree list
  • In the upper right hand corner there are the links Source | Contents | Index | Style Source | Contents | Index | Style Source | Contents | Index | Style . Click on the Index link.
  • What is St ?

    St is defined as

    type St r = RWS () Text Int r
    

    RWS is just a monad which has Reader, Writer and State capabilities. The Reader environment is () , it writes Text values and an Int for state.

    It's a convenience definition (available from the mtl package) so you don't have to build up your own monad transformer stack using ReaderT , WriterT and StateT .

    Note that the reader environment is () which means that library is only really using the writer and state aspects of the monad.

    How does box ... >= box ... work?

    The box function has type:

    box :: Selector -> (Double, Double) -> St (Var' Selection)
    

    which means it takes a Select and a pair of Doubles and returns a Var' Selector in the St monad.

    The expression box "#div1" (300,300) >>= bars n 300 (Data1D [...]) is the same as:

    do vs <- box "#div1" (300,300)
       bars n 300 (Data1D [...]) vs
    

    Interpretation:

  • Run the box function to create a Var' Selection . This happens in the St monad.
  • Call bars with the Var' Selection returned by step 1.
  • What's the difference between a Var' Selection and a Selection ? Honestly I'm not sure.

    The >>> operator

    >>> is an Arrow operator. Arrows is a way of expressing computations as a pipeline of operations. The examples on this page should give you an idea of how it's used:

    https://www.haskell.org/arrows/syntax.html

    Note that >>> is defined in terms of a type-class, so exactly what it does depends on what types you are using it with. In this case it is being used with Chain () Selection values.

    If you read the docs for Chain (link) you'll see the comment:

    Chain ab behaves just like (a -> b). Val Var is the starting point of chain (= constant), and Nil is the termination of chain.

    So this fragment:

                                                -- type:
    d3Root >>> select parent                    -- Chain () Selection
           >>> func "append" [PText "svg"]      -- Chain a b
           >>> width w                          -- Chain a a
           >>> height h                         -- Chain a a
           >>> style ...                        -- Chain a a
    

    can be read as:

  • Start with the d3 object. This returns a selection.
  • Select the parent of that selection.
  • Call the JS function append with argument "svg"
  • Set the width then the height and then the style
  • What's interesting is that the func function has type Chain ab -- it has an unrestricted return type b . That's why I suspect there is the explicit type signature at the end, eg :: Chain () Selection .


    as @delta already said hoogle is your friend - the imported piece here is from Control.Category - and it denotes the Left-to-right composition of morphisms.

    The category at hand in this case is the Kleisli Category associated to a monad just a sub-category of Hask - then the >>> operator is the missing link to make functions like

     f :: m a -> m b
     g :: m b -> m c
    

    work properly with each other. while

    >>= :: m a -> (a -> m b) -> m b
    

    would not be able to do that, the specialized version of (>>>)

    >>> :: (m a -> m b) -> (m b -> m c) -> ma -> m c
    

    would give you h = (f >>> g) a correct output.

    链接地址: http://www.djcxy.com/p/43250.html

    上一篇: Haskell:使用unsafePerformIO进行全局常量绑定

    下一篇: Haskell中运算符`>>>`和`>> =`如何工作?