2016-05-19 4 views
2

Я читал через Haskell d3js библиотеки:Как операторы `>>>` и `>> =` работают в Haskell?

Это код, определяющий Haskell окно:

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) 

код на самом деле экспорт с помощью функции box в d3.js коде используется оператор >>=, как это :

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])) 

Для того, чтобы избежать, как это непопулярно вопрос по стрелкам: How to use arrow operators in haskell Где я могу найти сигнатуры типа или другую основную информацию? Существуют ресурсы, где я могу узнать больше о:

Первый был легко найти, но ответ был запутанным:

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

Я обнаружил, что f $ a b c = f ((a b) c) в то время как f a b c = (((f a) b) c

Prelude дает подобный ответ для >>= с участием монад. В моем случае это может быть монада IO. Или заявление d3js монада St()

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

Последняя не появляется вообще ... что это очень плохо, потому что это выглядит довольно существенным

*Main Lib> :t (>>>) 

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

Наконец на риск связывая слишком много вопросов сразу. Может кто-нибудь объяснить эту подпись типа? Особенно последний пункт:

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

try https://www.haskell.org/hoogle/ – delta

+1

'>>>' фактически определен в 'Control.Category' сейчас. ('Category' является суперклассом' Arrow'.) – chepner

+0

Что касается вашего последнего вопроса - я бы попросил вас ответить на встречный вопрос - что вы поняли об этом - и что вас беспокоит. Вы рассматривали определения каждого типа? – epsilonhalbe

ответ

3

Индекс пакет

Пакеты на Hackage обычно индексной страницы всех функций/типов/и т.д. определены. Индекс для пакета d3js находится здесь:

Вы можете получить там:

  1. Посетите титульный лист для пакета
  2. Нажмите на любое имя модуля в списке дерева экспортированных модулей
  3. В правом верхнем углу находятся ссылки Source | Contents | Index | Style. Нажмите ссылку «Индекс».

Что такое St?

St определяется как

type St r = RWS() Text Int r 

RWS просто монада, которая имеет читателей, Writer и государственные возможности. Среда чтения составляет (), она записывает Text значения и Int для состояния.

Это определение удобства (доступен из mtl пакета), поэтому вам не придется создать свой собственный стек монада трансформаторов с использованием ReaderT, WriterT и StateT.

Обратите внимание, что среда чтения составляет (), что означает, что библиотека действительно использует авторские и государственные аспекты монады.

Как работает box ... >= box ...?

box функция имеет вид:

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

что означает, что требуется Select и парой двойников и возвращает Var' Selector в St монады.

Выражение box "#div1" (300,300) >>= bars n 300 (Data1D [...]) такое же, как:

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

Интерпретация:

  1. запустить функцию box создать Var' Selection.Это происходит в монаде St.
  2. Вызов bars с Var' Selection возвращенное шагом 1.

Какая разница между Var' Selection и Selection? Честно говоря, я не уверен.

>>> оператор

>>> является оператором Стрелка. Стрелки - это способ выражения вычислений как конвейер операций. Примеры на этой странице должно дать вам представление о том, как она используется:

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

Обратите внимание, что >>> определяется в терминах типа класса, так что именно он делает, зависит от того, что типа вы используете его с. В этом случае он используется с значениями Chain() Selection.

Если вы читаете документацию для Chain(link) вы увидите комментарий:

цепь а б ведет себя так же, как (а -> б). Val Var является отправной точкой цепочки (= константа), а Nil - прекращением цепи.

Так этот фрагмент:

          -- 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 

можно прочитать как:

  1. Start с объектом d3. Это возвращает выбор.
  2. Выберите родительский элемент этого выбора.
  3. Вызов функции JS append с аргументом "svg"
  4. Установите ширину затем высоту, а затем стиль

Что интересно, что функция func имеет тип Chain a b - он имеет неограниченный тип возвращаемого b. Вот почему я подозреваю, что в конце есть явная подпись типа, например. :: Chain() Selection.

1

, как @delta уже сказал hoogle ваш друг - импортированная часть здесь от Control.Category - и это означает влево-вправо состав морфизмов.

Категория под рукой в ​​данном случае является Клейсли Категория связана с монады только подкатегорию HASK - то оператор >>> является отсутствует ссылку, чтобы такие функции, как

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

нормально работать друг с другом.в то время как

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

не будет в состоянии сделать это, специализированная версия (>>>)

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

даст вам h = (f >>> g) правильный вывод.

+1

Я бы не назвал 'm a -> m b' Kleisli. Это всего лишь подкатегория ** Hask **. 'a -> m b' будет Клейсли.На самом деле '>> =' (точнее, '> =>') составляет стрелки Kleisli в форме простой функции, но '>>>' могут составлять их только в [их завернутой форме] (http: //hackage.haskell. орг/пакет/база-4.8.2.0/Docs/Control-Arrow.html # т: Клейсли). – leftaroundabout

+0

ой - это было долгое недопонимание с моей стороны - спасибо, что сказал мне – epsilonhalbe

Смежные вопросы