我正在研究以下一小段代码:
import Control.Monad
import Data.Aeson
import qualified Data.HashMap.Strict as HashMap
import Data.Map (Map)
import qualified Data.Map as Map
import GHC.Generics
-- definitions of Whitelisted, WhitelistComment and their FromJSON instances
-- omitted for brevity
data Whitelist = Whitelist
{ whitelist :: Map Whitelisted WhitelistComment
} deriving (Eq, Ord, Show)
instance FromJSON Whitelist where
parseJSON (Object v) =
fmap (Whitelist . Map.fromList) . forM (HashMap.toList v) $ \(a, b) -> do
a' <- parseJSON (String a)
b' <- parseJSON b
return (a', b')
parseJSON _ = mzero
当我意识到我可以do
用应用风格重写块时:
instance FromJSON Whitelist where
parseJSON (Object v) =
fmap (Whitelist . Map.fromList) . forM (HashMap.toList v) $ \(a, b) ->
(,) <$> parseJSON (String a) <*> parseJSON b
parseJSON _ = mzero
并且我也可以forM
用for
. 在进行上述更改之前,我for
首先切换到:
instance FromJSON Whitelist where
parseJSON (Object v) =
fmap (Whitelist . Map.fromList) . for (HashMap.toList v) $ \(a, b) -> do
a' <- parseJSON (String a)
b' <- parseJSON b
return (a', b')
parseJSON _ = mzero
令我惊讶的是,这仍然编译。给定 的定义 for
:
for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b)
我认为Applicative
约束会阻止我在传递给for
.
我显然在这里遗漏了一些基本的东西,无论是for
签名的真正含义,还是我发布的代码是如何被编译器解释的,如果能帮助理解正在发生的事情,我将不胜感激。