簡體   English   中英

如何到內心也許monad從purescript中的html按鈕中提取類名?

[英]How to get to inner Maybe monad to extract class name from html button in purescript?

我正在嘗試學習purescript

我在某些HTML中有一個按鈕,我正在嘗試打印類名。 我建立和browserifying使用pulp

我正在使用的函數是querySelector:

import Web.DOM.ParentNode (querySelector)

這會在兩個“框”內返回我想要的項目Element :一個外部效果monad和一個嵌入的Maybe monad:

> :type querySelector
QuerySelector -> ParentNode -> Effect (Maybe Element)

我的效果monad看起來像:

getBtn ::  Effect Unit
getBtn = do
  doc <- map toParentNode (window >>= document)
  button <- querySelector (wrap "#btn") doc
  ... Need to extract class name from 'button' here

我知道我可以通過在外部效果monad上調用bind(>> =)來到內部。 我的第一個攻擊計划是使用可能的功能手動取消裝箱。 以下是如何為簡單的Int執行此操作:

> maybe 0 (\x -> x) $  Just 7
7

對於一個可能的元素,我認為它看起來像:

unboxMaybeElement :: Maybe Element -> Element
unboxMaybeElement Nothing = Nothing
unboxMaybeElement (Just a) = maybe (Element ..note: trying to create a default element here) (\x -> x) a 

一個問題是我找不到類型Element的構造函數,所以我無法提供默認值( 也許是第一個arg),所以我不能使用這個方法。

另外,我找不到Element類型的定義。

我還讀到,無論如何都要進入一個Maybe並不是一個好主意,而是通過使用fmap函數(如map或fmap )來解除對它的功能。

在這種情況下,我試圖調用外部函數,如:

  button <- querySelector (wrap "#btn") doc
  let cn = getClassName button
  log $ "classname=" <> show cn

-- The basic question is how to implement this function?
getClassName :: Maybe HTMLElement -> String
getClassName e = map className  (map fromElement e)

注意:在Web.HTML.HTMLElement中提供了classNamefromElement

正如你所看到的,我試圖通過用地圖調用函數來提升函數,因為函數處理Maybes,但我陷入了“Maybe Element”和“Element”之間的類型沖突的困境中“和”HTMLElement“與”元素“等

是的,我承認我在這里遇到了一些問題,這不是一個真正的初學者問題,但它讓我感到非常困難,因為獲取HTML對象的類名非常簡單。 當然,我一定錯過了什么?

順便說一句,這是我的HTML:

<!doctype html>
<html>
  <body>
    <script src="index.js"></script>
    <p>
      <input type="button" class="btn-class" value="click me" id="btn"/>
    </p>
  </body>
</html>

更普遍的問題是:如何深入嵌套兩個monad級別的值?

根據我在本視頻中看到的一些類似代碼,我能夠獲得編譯的內容。 我不是說這是最好的方式,甚至是一種好方法,只是它有效:

getBtn ::  Effect Unit
getBtn = do
  log "now in getBtn"
  doc <- map toParentNode (window >>= document)
  mbtn <- querySelector (wrap "#btn") doc
  case mbtn of
    Nothing -> log "mbtn failed"
    Just btn -> do
      let mhtmlEl = fromElement btn
      case mhtmlEl of
        Nothing -> log "mhtml failed"
        Just htmlEl -> do
          let cn = className htmlEl
          log $ "classname below:"
          cn >>= log
          pure unit
      pure unit
  pure unit
pure unit

某些變量名稱(“mbtn”,“mhtmlEl”)上的“m”可能表示它是一個包裹的對象,即monadic。 在你的是很重要的case Just語句指定不同的變量比case of發言,一個沒有前一個“M”(“BTN”,“htmlEl”),表示這是一個原始或展開值。

pure unit線基本上是虛線,以滿足monad總是返回“binder”(let或'< - '賦值)以外的其他要求的要求,因此根據你的工作流程如何,你可能需要也可能不需要它們建造。

在這個例子中實際上有兩個Maybe級別:一個在querySelector結果上,一個在fromElement結果上。 倒入另一do處理原始HTMLElement ,你就多達三個層次do

不幸的是, querySelector似乎為我返回Nothing ,但這是一個正交問題。 這是打印className的全部動機 - 確定它是否正在查找元素。

實際上你通過自己調查這個問題做得很好,我可以根據你提供的例子建議重構。

假設我們不關心在特定情況下記錄失敗的消息。 這意味着,我們可以用pure unit替換每一個這樣的日志記錄:

getBtn ::  Effect Unit
getBtn = do
  log "now in getBtn"
  doc <- map toParentNode (window >>= document)
  mbtn <- querySelector (wrap "#btn") doc
  case mbtn of
    Nothing -> pure unit
    Just btn -> do
      let mhtmlEl = fromElement btn
      case mhtmlEl of
        Nothing -> pure unit
        Just htmlEl -> do
          let cn = className htmlEl
          log $ "classname below:"
          cn >>= log

然后我們可以注意到一個有趣的模式:

case mbtn of
  Nothing -> pure unit
  Just btn -> do
    let mhtmlEl = fromElement btn

即我們想要在btn值上應用fromElement函數,如果它Just btn或什么也不做,如果它Nothing 結果類型必須是Maybe值。

第一個想法是使用map函數,但fromElement的類型是fromElement :: Element -> Maybe HTMLElement ,因此結果類型將是Maybe (Maybe a))

無論如何,我們甚至可以按類型搜索這樣的函數,第一個結果是bind (與(>>=)相同)。 所以讓我們重構(將類型指向注釋只是為了清晰,但確定沒有必要):

getBtn ::  Effect Unit
getBtn = do
  log "now in getBtn"
  doc <- map toParentNode (window >>= document)
  mbtn <- querySelector (wrap "#btn") doc

  let mhtmlEl = fromElement =<< mbtn -- Maybe HTMLElement

  case mhtmlEl of
    Nothing -> pure unit
    Just htmlEl -> do
      let cn = className htmlEl
      log $ "classname below:"
      cn >>= log

下一步是減少另一個case表達式。 這里使用map (與<$>相同)就足夠了:

getBtn ::  Effect Unit
getBtn = do
  log "now in getBtn"
  doc <- map toParentNode (window >>= document)
  mbtn <- querySelector (wrap "#btn") doc

  let mhtmlEl = (fromElement =<< mbtn) -- Maybe HTMLElement
  let mCn = className <$> mhtmlEl -- Maybe (Effect String)

  case mCn of
      Nothing -> log "no such element"
      Just cn -> do
          log $ "classname below:"
          cn >>= log

結果類型的getBtn函數必須是Effect Unit ,因此必須在此處處理Maybe值的每個case。 我會這樣離開,因為很清楚,這里發生了什么。 但是,如果你尋找一個簡潔的表示,那么maybe功能可以應用在這里:

getBtn ::  Effect Unit
getBtn = do
  log "now in getBtn"
  doc <- map toParentNode (window >>= document)
  mbtn <- querySelector (wrap "#btn") doc

  let mhtmlEl = (fromElement =<< mbtn) -- Maybe HTMLElement
  let mCn = className <$> mhtmlEl -- Maybe (Effect String)

  maybe (log "no such element") (\cn -> log "classname below:" *> cn >>= log) mCn

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM