代码之家  ›  专栏  ›  技术社区  ›  M. Walker

Purescript效果:防止深嵌套

  •  1
  • M. Walker  · 技术社区  · 6 年前

    马上 main

    main :: Eff (dom :: DOM) (Maybe (Eff (dom :: DOM) (Maybe Element)))
    

    我想要以下内容:

    main :: Eff (dom :: DOM) (Maybe Element)
    

    findItem :: forall e. IsElement e => e -> Eff (dom :: DOM) (Maybe Element)
    findItem e = getElementsByClassName "thing" (toElement e) >>= (item 0)
    
    -- main :: Eff (dom :: DOM) (Maybe Element)
    main = (map findItem) <$> (window >>= document >>= body)
    

    最好的方法是什么?

    当然,我可以做到以下几点:

    findItem :: forall e. IsElement e => Maybe e -> Eff (dom :: DOM) (Maybe Element)
    findItem (Just e) = getElementsByClassName "findItemEdit" (toElement e) >>= (item 0)
    findItem Nothing = pure Nothing
    
    main :: Eff (dom :: DOM) (Maybe Element)
    main = findItem =<< body =<< document =<< window
    

    但我不想 Maybe 在中处理 findItem 作用

    3 回复  |  直到 6 年前
        1
  •  3
  •   ephrion    6 年前

    使用 traverse :: forall a b eff. (a -> Eff eff b) -> Maybe a -> Eff eff (Maybe b) . 该函数更通用,但这就是您想要使用它的方式。每当你发现自己想“交换”两种类型时,比如 Maybe a -> Eff eff (Maybe a) Maybe (List a) -> List (Maybe a) ,您可以使用 traverse sequence .

    具体来说 main 看起来像:

    main :: Eff (dom :: DOM) (Maybe Element)
    main = do
      mdocBody <- window >>= document >>= body
      mmitem <- traverse findItem mdocBody
      -- mmitem has type `Maybe (Maybe Element)`
      -- we can use `join` to collapse
      pure (join mmitem)
    

    或者,作为无点,

    main :: Eff (dom :: DOM) (Maybe Element)
    main =
      window >>= document >>= body 
        >>= map join <<< traverse findItem  
    
        2
  •  3
  •   Sam Thomson    6 年前

    您可以使用 MaybeT monad变压器:

    main = runMaybeT do
      b <- MaybeT (window >>= document >>= body)
      MaybeT (findItem b)
    

    MaybeT 是的新类型 Maybe 包裹在单子里 m (在我们的情况下 m级 Eff (dom :: DOM) ):

    newtype MaybeT m a = MaybeT (m (Maybe a))
    

    及其 bind 以您希望的方式处理嵌套和取消嵌套:

    bind (MaybeT x) f = MaybeT do
      x >>= case _ of
        Nothing -> pure Nothing
        Just y -> case f y of MaybeT m -> m
    
        3
  •  0
  •   Fyodor Soikin    6 年前

    我能想到的最好办法就是使用 Maybe 本质上需要 findItem 从您的第一个示例中 芬迪特姆 从您的第二个示例中:

    main :: Eff (dom :: DOM) (Maybe Element)
    main = maybe (pure Nothing) findItem =<< body =<< document =<< window