我对 Yesod 完全陌生(并且在 haskell 方面不是很有经验),我正在尝试构建我的第一个处理程序。我使用默认参数对我的应用程序进行了脚手架(我使用的是 Yesod 0.9.4.1 版本并在脚手架中选择 postgresql),现在我正在尝试使用 selectList 从表中检索一些数据。我在模型配置文件中定义了一个新表(我们称之为 Foo):
Foo
xStart Int
yStart Int
并且想要传递 FooId 和其他一些 Foo 属性的列表,所以我定义了一个路由:
/foos/#Int/#Int/*FooId FoosReturnR GET
和一个处理程序:
module Handler.FoosReturn where
import Import
selectWindowSize :: Int
selectWindowSize = 10000
getFoosReturnR :: Int -> Int -> [FooId] -> Handler RepPlain
getFoosReturnR x y withoutIds = do
foos <- runDB $ selectList [FooId /<-. withoutIds,
FooXStart <. x + selectWindowSize,
FooXStart >=. x - selectWindowSize,
FooYStart <. y + selectWindowSize,
FooYStart >=. y - selectWindowSize] []
return $ RepPlain $ toContent $ show foos
我在 Application.hs 中导入了处理程序并将其添加到 cabal 文件中,现在当我尝试运行它时,我收到一条错误消息,指出 FooId 不是 MultiPiece 的实例 - 但是当我尝试使其成为实例时,有一个错误说 FooId 是类型同义词并且不能是 MultiPiece 的实例 - 如何解决此问题?
编辑:丹尼尔:嗯,实际上我不知道 FooId 到底是什么——它是 Yesod 魔法的一部分,到目前为止我还不完全理解——它是从表定义中自动生成的——但它是某种数字。
因为我不知道如何使用 MultiPiece 我切换到更简单的解决方案并修改:
路线:/foos/#Int/#Int/#String FoosReturnR GET
处理程序:[还添加了一些日志记录]
module Handler.FoosReturn where
import Import
import Data.List.Split
import qualified Data.Text.Lazy as TL
selectWindowSize :: Int
selectWindowSize = 10000
getFoosReturnR :: Int -> Int -> String -> Handler RepPlain
getFoosReturnR x y withoutIds = do
app <- getYesod
liftIO $ logLazyText (getLogger app) ("getFoosReturnR('" `TL.append` (TL.pack $ (show x) ++ "', '" ++ (show y) ++ "', '" ++ withoutIds ++ "') "))
foos <- runDB $ selectList [FooId /<-. (map (\a -> read a :: FooId) $ splitOn "," withoutIds),
FooXStart <. x + selectWindowSize,
FooXStart >=. x - selectWindowSize,
FooYStart <. y + selectWindowSize,
FooYStart >=. y - selectWindowSize] []
return $ RepPlain $ toContent $ show foos
现在它正在编译但是当我浏览到:http://localhost:3000/sectors/1/1/1,2我得到一个页面只包含: Internal Server Error Prelude.read: no parse
好吧,我不完全理解这里的 FooId 是什么 - 如何从包含数字的字符串列表中创建这样的 FooId 列表?
当然,最需要如何使 FooId 成为 MultiPiece 实例的解决方案。
编辑:
Daniel 和 svachalek,感谢您的帖子 - 我尝试了您的(Daniel 的)解决方案,但后来我收到错误说 [FooId] 是预期的(如在处理程序函数声明中)但是 FooId 类型被给出,这导致我下面的解决方案:
data FooIds = FooIds [FooId] deriving (Show, Read, Eq)
instance MultiPiece FooIds where
toMultiPiece (FooIds fooList) = map (Data.Text.pack . show) fooList
fromMultiPiece texts =
if length (filter isNothing listOfMaybeFooId) > 0
then Nothing
else Just $ FooIds $ map fromJust listOfMaybeFooId
where
listOfMaybeFooId = map constructMaybeFooId texts
constructMaybeFooId :: Text -> Maybe FooId
constructMaybeFooId x = case reads (Data.Text.unpack x) :: [(FooId,String)] of
[(foo,_)] -> Just foo
_ -> Nothing
当然,我将路线更改为:/foos/#Int/#Int/*FooIds FoosReturnR GET
和处理程序:
getFoosReturnR :: Int -> Int -> FooIds -> Handler RepPlain
getFoosReturnR coordX coordY (FooIds withoutIds) = do
现在我在编译和运行时都没有遇到任何错误,唯一不满意的是我总是收到 Not Found 结果,即使我提供了应该给我一些结果的参数 - 所以现在我必须弄清楚如何确定准确发送到数据库的 SQL
编辑:
现在我看到“未找到”与问题有关,并且上述编辑不是解决方案 - 当我浏览到 localhost:3000/foos/4930000/3360000 然后我得到结果(但后来 FooIds 是空的) - 但是当我添加如下内容时:localhost:3000/sectors/4930000/3360000/1 然后我总是得到“未找到” - 所以它仍然无法正常工作..