Понимание Purescript Eff Monad и блоков do

Я пытаюсь понять, почему следующее не работает в Purescript. У меня есть чувство, что на него также может ответить сообщество Haskell, поэтому я перечислил его.

Общая суть:

Если у меня есть блок do, могу ли я не добавить одноразовое значение? В этом случае я пытаюсь зарегистрировать что-то (подобное print в Haskell) в середине серии монадических вычислений.

main = do
    a <- someAction1
    b <- someAction2
    _ <- log "here is a statement I want printed"
    someAction3 a b

В частности, у меня есть функция, которая принимает следующее (из примера проекта шаблона Halogen)

data Query a = ToggleState a

eval :: Query ~> H.ComponentDSL State Query g
eval (Toggle next) = do
    H.modify (\state -> state { isOn = not state.isOn })
    _ <- log "updating the state!"
    pure next

На мой взгляд, это должно работать как в Haskell

barf :: IO Int
barf = do
  _ <- print "Here I am!"
  return 5

main :: IO ()
main = do
  a <- barf
  _ <- print $ "the value is: " ++ (show a)
  print "done"

В частности, ошибка, которую я получаю, - это несоответствие типов монад

Не удалось сопоставить тип Eff с типом Free при попытке сопоставить тип Eff ( "console" :: CONSOLE | t6 ) с типом Free (HalogenFP t0 { "isOn" :: t1 | t2 } t3 t4) ... и т. Д.

Я знаю, что purescript заставляет меня объявлять «вещи, которых я касаюсь в монаде» (т.е. forall e. Eff ( a :: SOMEVAR, b :: SOMEOTHERVAR | eff ) Unit, но я не уверен, как это сделать в данном случае ...


person clo_jur    schedule 12.01.2017    source источник
comment
Если это просто для отладки, вам может быть интересно использовать вместо него модуль Debug.Trace из purescript-debug иметь дело с распространением эффектов повсюду, что довольно обременительно для временного ведения журнала отладки. Однако вы не должны использовать это ни для чего, кроме отладки, как следует из названия.   -  person Alexis King    schedule 12.01.2017
comment
@AlexisKing Это не для отладки, а для того, чтобы иметь возможность быстро отправить сообщение. Кроме того, я хотел бы знать, почему это не работает для моего собственного образования.   -  person clo_jur    schedule 12.01.2017
comment
H.modify дает Free .. .., а log дает Eff .. .. - ошибка сообщает вам, что это разные типы. Вы не можете использовать их в одном do блоке.   -  person user2407038    schedule 12.01.2017


Ответы (1)


Если вы работаете с галогеном версии 0.12.0, у вас должна быть возможность использовать fromEff из https://pursuit.purescript.org/packages/purescript-aff-free/3.0.0/docs/Control..Monad.Aff.Free#v:fromEff вот так:

data Query a = ToggleState a

eval :: Query ~> H.ComponentDSL State Query g
eval (Toggle next) = do
    H.modify (\state -> state { isOn = not state.isOn })
    _ <- H.fromEff (log "updating the state!")
    pure next

Это будет намного лучше в следующих версиях галогена (> = 0,13), в которых liftEff должно быть достаточно.

Причина, по которой вы не можете сразу использовать log, заключается в том, что H.ComponentDSL не является синонимом типа для Eff, а для Free, и поэтому вы не можете просто смешивать действия Eff и ComponentDSL.

person Christoph Hegemann    schedule 12.01.2017
comment
ах спасибо. Я упустил свою попытку использовать liftEff, так как был сбит с толку, почему он не поднимается до правильного контекста. - person clo_jur; 12.01.2017
comment
Однако мне все еще не удается успешно поднять монаду Эфф. Я считаю, что мне нужно указать тип в аннотации ?? Это компилятор? - person clo_jur; 12.01.2017
comment
вы не можете больше сохранять g полностью полиморфным. Он используется для переноса эффектов, используемых в вашей программе. См. github.com/slamdata/purescript -halogen / blob / v0.12.0 / examples / в качестве примера. Вы хотите заменить ajax :: AJAX на console :: CONSOLE - person Christoph Hegemann; 12.01.2017