Haskell:从Maybes结构转换为Hashmap
我经常出现一种模式。我有一个这样的结构:Haskell:从Maybes结构转换为Hashmap,haskell,haskell-lens,Haskell,Haskell Lens,我经常出现一种模式。我有一个这样的结构: data Foo = Foo { foo :: Maybe Text , bar :: Maybe Text , buz :: Maybe Text } 我想将其转换为带有标签值的贴图,不丢弃任何值: myMap :: [(Text, Text)] 例如:myMap=[(“foo”,“val1”),(“bar”,“val2”)] 最优雅的方式是什么? 我尝试了一些模式,比如if is just。。。然后我就。。。除此之外,什么都
data Foo = Foo
{ foo :: Maybe Text
, bar :: Maybe Text
, buz :: Maybe Text
}
我想将其转换为带有标签值的贴图,不丢弃任何值:
myMap :: [(Text, Text)]
例如:myMap=[(“foo”,“val1”),(“bar”,“val2”)]
最优雅的方式是什么?
我尝试了一些模式,比如if is just。。。然后我就。。。除此之外,什么都不做,然后使用catMaybes
,但在我看来它不是很优雅
实际上,我的结构更加异构:
data Foo = Foo
{ foo :: Maybe Text
, bar :: Maybe Bool
, buz :: Maybe Int
}
我想把它转换成:
myMap :: [(Text, Value)]
有没有一种镜头方式可以做到这一点?不是镜头,但至少列表理解很简单:
quux :: Foo -> [(String, Text)]
quux v = [ (a,b) | (a, Just b) <- zip ["foo", "bar", "buz"]
$ map ($ v) [foo, bar, buz]]
是的,这很快就会变得脆弱和笨拙。但是第一个变体非常简单。我们可以让Haskell自动派生ToJson的实例:
{-# LANGUAGE DeriveGeneric #-}
import Data.Text(Text)
import Data.Aeson(ToJSON)
import GHC.Generics(Generic)
data Foo = Foo
{ foo :: Maybe Text
, bar :: Maybe Bool
, buz :: Maybe Int
} deriving Generic
instance ToJSON Foo
例如:
Prelude> kvs (Foo Nothing (Just True) (Just 14))
[("buz",Number 14.0),("bar",Bool True)]
类型签名,如myMap::[(文本,值)]
似乎意味着所有字段都具有相同的类型。列表必须是同质的。@jpmarinier抱歉,我忘了提到它是来自Aeson的值:@cdupont:您可以让Haskell自动为ToJson
派生一个实例,然后使用它生成键值对。非常感谢,我喜欢列表理解。虽然我总是忘记使用它们…非常感谢,我认为这是最好的解决方案。
{-# LANGUAGE DeriveGeneric #-}
import Data.Text(Text)
import Data.Aeson(ToJSON)
import GHC.Generics(Generic)
data Foo = Foo
{ foo :: Maybe Text
, bar :: Maybe Bool
, buz :: Maybe Int
} deriving Generic
instance ToJSON Foo
import Data.Aeson(Value(Null, Object), toJSON)
import Data.HashMap.Strict(toList)
kvs :: Foo -> [(Text, Value)]
kvs foo
| Object obs <- toJSON foo = filter ((Null /=) . snd) (toList obs)
| otherwise = []
Prelude> kvs (Foo Nothing (Just True) (Just 14))
[("buz",Number 14.0),("bar",Bool True)]