首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >buildQueryString函数的Purescript类型

buildQueryString函数的Purescript类型
EN

Stack Overflow用户
提问于 2017-06-26 10:56:30
回答 2查看 271关注 0票数 3

我是Purescript的新手,我正在尝试编写一个函数,它可以获取任何记录值,并在字段和值上迭代,并构建一个查询字符串。

我的想法是:

代码语言:javascript
复制
buildQueryString :: forall a. PropertyTraversible r => r -> String

我想这样用:

代码语言:javascript
复制
buildQueryString {name: "joe", age: 10}      -- returns: "name=joe&age=10"

是否有一种方法可以用现有的成语在Purescript中编写类似的东西,还是必须为此创建自己的自定义类型类?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-27 06:42:59

这在纯仿制药中是可能的,但它只适用于名义类型,而不适用于任何记录。但是它节省了样板,因为您只需要为Generic派生实例,因此它可以在不需要进一步修改的情况下与任何datanewtype一起工作。

缺点是,您必须对类型做一些假设:就像它只包含一个记录,而记录不包含数组或其他记录。

下面是一个令人讨厌的演示,它将如何工作:

代码语言:javascript
复制
data Person = Person 
            { name   :: String
            , age    :: Int
            }

derive instance genericPerson :: Generic Person

joe = Person { name: "joe", age: 10 }

build :: GenericSpine -> String
build (SRecord arr) = intercalate "&" (map (\x -> x.recLabel <> "=" <> build (x.recValue unit)) arr)
build (SProd _ arr) = fromMaybe "TODO" $ map (\f -> build (f unit)) (head arr)
build (SString s)   = s
build (SInt    i)   = show i
build _             = "TODO"

test = build (toSpine joe)

纯抄本-泛型-代表是新的,所以可能有一个更好的解决方案,甚至在任何记录。我还没试过。

票数 0
EN

Stack Overflow用户

发布于 2017-06-29 00:02:49

我确信它可以更短,但是下面是基于purescript-generic-rep (受genericShow启发)的实现。这个解决方案使用类型分类--它似乎是generic-rep的标准方法。

代码语言:javascript
复制
module Main where

import Prelude

import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Data.Foldable (intercalate)
import Data.Generic.Rep (class Generic, Constructor(..), Field(..), Product(..), Rec(..), from)
import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol)

class EncodeValue a where
  encodeValue ∷ a → String

instance encodeValueString ∷ EncodeValue String where
  encodeValue = id

instance encodeValueInt ∷ EncodeValue Int where
  encodeValue = show

class EncodeFields a where
  encodeFields :: a -> Array String

instance encodeFieldsProduct
  ∷ (EncodeFields a, EncodeFields b)
  ⇒ EncodeFields (Product a b) where

  encodeFields (Product a b) = encodeFields a <> encodeFields b

instance encodeFieldsField
  ∷ (EncodeValue a, IsSymbol name)
  ⇒ EncodeFields (Field name a) where

  encodeFields (Field a) =
    [reflectSymbol (SProxy :: SProxy name) <> "=" <> encodeValue a]

buildQueryString
  ∷ ∀ a l n.
    Generic n (Constructor l (Rec a))
  ⇒ (EncodeFields a)
  ⇒ n
  → String
buildQueryString n =
  build <<< from $ n
 where
  build (Constructor (Rec fields)) = intercalate "&" <<< encodeFields $ fields

newtype Person =
  Person
    { name   ∷ String
    , age    ∷ Int
    }
derive instance genericPerson ∷ Generic Person _

joe ∷ Person
joe = Person { name: "joe", age: 10 }

main :: forall e. Eff (console :: CONSOLE | e) Unit
main = do
  log <<< buildQueryString $ joe

buildQueryString期望类型值具有单个构造函数,该构造函数包含一个记录(可能只是newtype),因为不可能为“未包装”Record类型派生Generic实例。

如果您还想处理Array值等,那么encodeValue可能会返回Array String类型的值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44758148

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档