Haskell 如何代表;数据。地图文本“文本”;在达尔?
如果我在Haskell中有这样的类型:Haskell 如何代表;数据。地图文本“文本”;在达尔?,haskell,yaml,dhall,Haskell,Yaml,Dhall,如果我在Haskell中有这样的类型: data MyType = MyType { env :: Map Text Text } main :: IO () main = do x <- input auto "./config" print (x :: MyType) env: KEY1: "foo" KEY2: "bar" 如何在Dhall中表示MyType的值 { env = ??? } 我想做的是在Dhall中写入MyType的值,然后从H
data MyType = MyType
{ env :: Map Text Text
}
main :: IO ()
main = do
x <- input auto "./config"
print (x :: MyType)
env:
KEY1: "foo"
KEY2: "bar"
如何在Dhall中表示MyType
的值
{ env = ???
}
我想做的是在Dhall中写入MyType
的值,然后从Haskell中读入并将其解组到MyType
,如下所示:
data MyType = MyType
{ env :: Map Text Text
}
main :: IO ()
main = do
x <- input auto "./config"
print (x :: MyType)
env:
KEY1: "foo"
KEY2: "bar"
(您可以使用Aeson的
decodefile
)将上述内容解析为MyType
类型。经过一些挖掘,我找到了三个解决方法。如果你想跳到底部
最好的解决方法是
土地
截至2019-05-05,无法像现在这样在达尔表示地图
可以使用Aeson/YAML(尽管不支持本机toMap
功能
马上就来)。所以现在我们基本上必须使用一个同质的
记录。这有点笨重,但至少你有一个本地解组
如果我们想使用元组列表而不是映射,我们可以这样做:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RecordWildCards #-}
module Tuple where
import Dhall
import qualified Data.Text as T
data MyType = MyType { env :: [MyTuple] }
deriving (Generic, Show)
instance Interpret MyType
newtype MyTuple = MyTuple (T.Text, T.Text)
deriving (Interpret, Show)
-- input auto "{env = [{_1= \"HOME\", _2 = \"foo\"}] }" :: IO MyType
以上内容改编自,展示了一种
将IP地址解析为4元素元组
要解析为映射,我们可以执行以下操作:
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
module MapA where
import Data.Map (Map)
import Data.Text (Text)
import Dhall
import qualified Data.Map
data MyType = MyType { env :: Map Text Text }
deriving (Generic, Show)
data KeyValue a = KeyValue { mapKey :: Text, mapValue :: a }
deriving (Generic, Show)
toMap :: [KeyValue a] -> Map Text a
toMap keyValues = Data.Map.fromList (map adapt keyValues)
where
adapt (KeyValue {..}) = (mapKey, mapValue)
instance Interpret MyType
instance Interpret a => Interpret (KeyValue a)
-- Wrap `Map` in a newtype if you want to avoid an orphan instance
instance Interpret a => Interpret (Map Text a) where
autoWith options = fmap toMap (autoWith options)
-- input auto "{env = [{mapKey = \"HOME\", mapValue = \"foo\"}] }" :: IO MapA.MyType
以上是根据这一点改编的
. 这个想法是为了
看起来像{mapKey=X,mapValue=Y}
可解析的记录,然后
将此类记录的任何列表转换为地图。注意我们如何支持任何值
输入,而不仅仅是文本(因此我们可以在MyType
beMap text Int
中使用env
,或者
如果我们愿意的话,还有别的事情)。此解决方案只有1个类型变量a
用于映射中的值,但我认为可以使键更精确
通用的
经过一些调整后,我编译了以下内容,它支持这两种
键和值也是通用的:
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
module MapKV where
import Data.Map (Map)
import Data.Text (Text)
import Dhall
import qualified Data.Map
data MyType = MyType { env :: Map Text Text }
deriving (Generic, Show)
data MyTypeInts = MyTypeInts { envInts :: Map Integer Integer }
deriving (Generic, Show)
data KeyValue k v = KeyValue { mapKey :: k, mapValue :: v }
deriving (Generic, Show)
toMap :: Ord k => [KeyValue k v] -> Map k v
toMap keyValues = Data.Map.fromList (map adapt keyValues)
where
adapt (KeyValue {..}) = (mapKey, mapValue)
instance Interpret MyType
instance Interpret MyTypeInts
instance (Interpret k, Interpret v) => Interpret (KeyValue k v)
-- Wrap `Map` in a newtype if you want to avoid an orphan instance
instance (Ord k, Interpret k, Interpret v) => Interpret (Map k v) where
autoWith options = fmap toMap (autoWith options)
-- input auto "{env = [{mapKey = +1, mapValue = \"foo\"}] }" :: IO MapKV.MyType
-- input auto "{envInts = [{mapKey = +1, mapValue = -22 }] }" :: IO MapKV.MyTypeInts
最后,这里是一个避免使用Env
newtype包装器的孤立实例的版本:
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
module MapKV where
import Data.Map (Map)
import Dhall
import qualified Data.Map
data MyType = MyType { env :: Env }
deriving (Generic, Show)
newtype Env = Env (Map Text Text)
deriving (Eq, Generic, Show)
data KeyValue k v = KeyValue { mapKey :: k, mapValue :: v }
deriving (Generic, Show)
toMap :: Ord k => [KeyValue k v] -> Map k v
toMap keyValues = Data.Map.fromList (map adapt keyValues)
where
adapt (KeyValue {..}) = (mapKey, mapValue)
instance Interpret MyType
instance (Interpret k, Interpret v) => Interpret (KeyValue k v)
instance Interpret Env where
autoWith options = fmap (Env . toMap) (autoWith options)
-- input auto "{env = [{mapKey = \"HOME\", mapValue = \"foo\"}] }" :: IO MapKV.MyType