簡體   English   中英

多個運算符的評估順序以中綴形式

[英]Order of evaluation for multiple operators in infix form

鑒於這種:

 data Base = Base {
   key1 :: Text,
   key2 :: Text,
   key3 :: Text
 } deriving (Show)

instance FromJSON Base where
  parseJSON (Object v) = Base <$>
                         ((v .: "base123") >>= (.: "key1")) <*>  -- 1
                         ((v .: "base123") >>= (.: "key2")) <*>  -- 2
                         ((v .: "base123") >>= (.: "key3"))      -- 3

  parseJSON _ = mzero

前綴運算符<$><*><*>的應用順序是什么? 換句話說,如果我以前綴形式重寫它:

instance FromJSON Base where
      parseJSON (Object v) = Base <$> ((<*>) ((v .: "base123") >>= (.: "key1")) $ (<*>) ((v .: "base123") >>= (.: "key2")) ((v .: "base123") >>= (.: "key3")))

      parseJSON _ = mzero

(注意$運算符),將首先評估第二個<*>的右側部分,因為僅在這種情況下才有意義,因為第一個<*>需要2個參數? 並且由於它需要2個參數,因此我們也必須使用$

我可能會問我的問題,以致難以理解我的意思,但我希望你確實理解。

實際上您的前綴形式不是很正確,應該是這樣的:

parseJSON (Object v) = ((<*>)
                        ((<*>)
                         ((<$>) Base ((v .: "base123") >>= (.: "key1")))
                         (((v .: "base123") >>= (.: "key2"))))
                        (((v .: "base123") >>= (.: "key3"))))

上面的定義仍然不是完整的前綴形式。 您必須在左邊加上>>=.:使其完全前綴。 話雖這么說,要找到以infix形式表示的多個運算符的確切評估順序,建議您使用ghci進行操作,以獲取更多有關類型的見解。 首先,請檢查所有運算符的關聯性和優先順序:

λ> :i (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
infixl 4 <$>
λ> :i (<*>)
(<*>) :: f (a -> b) -> f a -> f b
infixl 4 <*>

因此,它們都保持關聯並且具有相同的優先級。 定義的中綴形式非常清楚如何進行評估:它們從左開始,首先在Base上應用<$> ,然后再應用兩個<*>函數。 類型Base最初應用於<$>

λ> :t Base
Base :: Text -> Text -> Text -> Base
λ> :t (Base <$>)
(Base <$>) :: Functor f => f Text -> f (Text -> Text -> Base)

現在,將((v .: "base123") >>= (.: "key1"))應用於上述類型的結果:

λ> let (Object v) = undefined :: Value
λ> :t (Base <$> ((v .: "base123") >>= (.: "key1")))
(Base <$> ((v .: "base123") >>= (.: "key1"))) :: Parser (Text -> Text -> Base)

您會看到它返回包裝在Parser類型中的函數。 Parser類型中提取基礎函數,必須使用<*>

λ> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
λ> :t (Base <$> ((v .: "base123") >>= (.: "key1")) <*>)
(Base <$> ((v .: "base123") >>= (.: "key1")) <*>) :: Parser Text -> Parser (Text -> Base)

您可以按照類似的步驟查看如何將其應用於函數定義的其他部分。 最后,您將獲得一種Parser Base

暫無
暫無

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

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