我尝试在为RESTful输出转到示例/api/v1.0/events?order=-id,title
时概括URL处理 - 因此结果将按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
分配给direction
,但编译器也不接受答案 0 :(得分:1)
问题是EventTitle
和EventUserId
属于不同的类型,因此您无法将其中的两个放在同一个列表中。但是,您可以将EventTitle
和EventContent
放在同一个列表中 - 它们都有EntityField Event Text
类型。
但是,以下方法应该有效(使用Yesod教程中的Person示例):
makeSelectOpt :: (Char,Char) -> SelectOpt Person
makeSelectOpt ('f','+') = Asc PersonFirstName
makeSelectOpt ('f','-') = Desc PersonFirstName
makeSelectOpt ('l','+') = Asc PersonLastName
makeSelectOpt ('l','-') = Desc PersonFirstName
makeSelectOpt ('a','+') = Asc PersonAge
makeSelectOpt ('a','-') = Desc PersonAge
makeSelections :: [(Char,Char)] -> [SelectOpt Person]
makeSelections = map makeSelectOpt
您可以将+/-处理分解为:
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 (SelectOpt Person)
:
makeSelectOpt'' :: (Char,Char) -> Maybe (SelectOpt Person)
makeSelectOpt'' ('f',dir) = Just $ updown dir $ PersonFirstName
makeSelectOpt'' ('l',dir) = Just $ updown dir $ PersonLastName
makeSelectOpt'' ('a',dir) = Just $ updown dir $ PersonAge
makeSelectOpt'' _ = Nothing
然后:
makeSelectOpts'' :: [(Char,Char)] -> Maybe [SelectOpt Person)
makeSelectOpts'' pairs = mapM makeSelectOpt'' pairs
如果所有对都有效,则结果为Just [...]
;如果无法识别其中任何一对,则结果为Nothing
。
<强>更新强>
这是另一种使用存在类型的方法,它看起来更像你的代码:
{-# 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"