[英]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中提供了className和fromElement 。
正如你所看到的,我試圖通過用地圖調用函數來提升函數,因為函數不處理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.