Haskell 如何用不同的EntityField值概括列表
例如,对于RESTful输出,我尝试将URL处理概括为Haskell 如何用不同的EntityField值概括列表,haskell,yesod,persistent,Haskell,Yesod,Persistent,例如,对于RESTful输出,我尝试将URL处理概括为/api/v1.0/events?order=-id,title,因此结果将按iddesc排序,而不是按titleasc排序 模型文件: -- models Event title Text content Text userId UserId deriving Eq deriving Show Haskell文件: -- Events.hs text2Order :: Text -> [S
/api/v1.0/events?order=-id,title
,因此结果将按id
desc排序,而不是按title
asc排序
模型文件:
-- models
Event
title Text
content Text
userId UserId
deriving Eq
deriving Show
Haskell文件:
-- Events.hs
text2Order :: Text -> [SelectOpt Event]
text2Order text =
case lookup textWithNoPrefix keyVal of
Just val -> [direction val]
Nothing -> error "wrong order"
where
keyVal = [ ("title", EventTitle)
, ("user" , EventUserId)
, ("id" , EventId)
]
textWithNoPrefix = if T.isPrefixOf "-" text
then T.tail text
else text
direction = if T.isPrefixOf "-" text
then Desc
else Asc
我似乎有两个问题:
keyVal
作为元组列表,其中第二个值不同Asc
或Desc
分配给方向
编译器也不接受它问题是
EventTitle
和EventUserId
属于不同的类型,因此不能将它们放在同一个列表中。但是,您可以将EventTitle
和EventContent
放在同一个列表中——它们都有类型EntityField事件文本
但是,类似以下的方法应该可行(使用Yesod教程中的Person示例):
您可以这样计算+/-处理:
updown '+' = Asc
updown _ = Desc
makeSelectOpt' :: (Char,Char) -> SelectOpt Person
makeSelectOpt' ('f',dir) = updown dir $ PersonFirstName
makeSelectOpt' ('l',dir) = updown dir $ PersonLastName
makeSelectOpt' ('a',dir) = updown dir $ PersonAge
如果要执行错误处理,请返回Maybe(选择opt Person)
:
然后:
makeSelectOpts'' :: [(Char,Char)] -> Maybe [SelectOpt Person)
makeSelectOpts'' pairs = mapM makeSelectOpt'' pairs
如果所有对都有效,则结果将是仅[…]
,如果其中任何一对未被识别,则结果将是无
更新
下面是另一种使用存在类型的方法,它看起来更像您的代码:
{-# LANGUAGE RankNTypes #-}
type ApplyToField = (forall t. EntityField Person t -> SelectOpt Person) -> SelectOpt Person
applyToFirstName, applyToLastName, applyToAge :: ApplyToField
applyToFirstName d = d PersonFirstName
applyToLastName d = d PersonFirstName
applyToAge d = d PersonAge
makeSelectOpt''' :: (Char,Char) -> SelectOpt Person
makeSelectOpt''' (fld,d) = fn (updown d)
where
table = [ ('f',applyToFirstName), ('l',applyToLastName), ('a',applyToAge) ]
fn = case lookup fld table of
Just f -> f
Nothing -> error "bad field spec"
谢谢分解方向有点困难,因为我们可以有id
和-id
(即no+id
)。不是真的-只返回一个Maybe(SelectOpt Person)。我会更新我的答案。好吧-我不会更新我的答案-我已经写够了。如果你觉得其中有什么有用的话,也许你可以投赞成票?该过程的要点是,将web参数规范化为规范形式,例如,一个字符对列表。然后,您可以使用我展示的内容将这些对转换为SelectOpt Person列表。如果某件事情没有意义或者需要忽略它,请在规范化步骤中执行此操作。规范化步骤只处理字符串,因此不会遇到任何棘手的类型问题。
makeSelectOpts'' :: [(Char,Char)] -> Maybe [SelectOpt Person)
makeSelectOpts'' pairs = mapM makeSelectOpt'' pairs
{-# LANGUAGE RankNTypes #-}
type ApplyToField = (forall t. EntityField Person t -> SelectOpt Person) -> SelectOpt Person
applyToFirstName, applyToLastName, applyToAge :: ApplyToField
applyToFirstName d = d PersonFirstName
applyToLastName d = d PersonFirstName
applyToAge d = d PersonAge
makeSelectOpt''' :: (Char,Char) -> SelectOpt Person
makeSelectOpt''' (fld,d) = fn (updown d)
where
table = [ ('f',applyToFirstName), ('l',applyToLastName), ('a',applyToAge) ]
fn = case lookup fld table of
Just f -> f
Nothing -> error "bad field spec"