如何使用多片
我对 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 的实例 - 如何解决此问题?
编辑: Daniel:嗯,实际上我不知道 FooId 到底是什么 - 它是 Yesod 魔法的一部分,到目前为止我还没有完全理解 - 它是从表定义中自动生成的 - 但它是某种数字。
因为我不知道如何使用 MultiPiece,所以我切换到更简单的解决方案并修改:
route: /foos/#Int/#Int/#String FoosReturnR GET
handler: [还添加了一些日志记录]
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 我得到的页面仅包含: 内部服务器错误 Prelude.read:没有解析
好吧,我不完全理解这里的 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 然后我总是得到“Not Found” - 所以它仍然不起作用..
I'm completely new to Yesod (and not very experienced in haskell) and I'm trying to build my first handler. I scraffolded my app using default parameters (I'm using Yesod 0.9.4.1 version and choose postgresql in scraffolding) and now I'm trying to retrieve some data from a table using selectList. I defined a new table (let's call it Foo) in models config file:
Foo
xStart Int
yStart Int
and want to pass a list of FooId's and some other Foo attributes so I defined a route:
/foos/#Int/#Int/*FooId FoosReturnR GET
and a handler:
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
I imported the handler in Application.hs and added it to cabal file and now when I'm trying to run it I receive an error saying that FooId is not an instance of MultiPiece - but when I try to make it an instance there is an error saying that FooId is a type synonym and cannot be an instance of MultiPiece - how to resolve this problem?
EDIT:
Daniel: well, actually I don't know what exactly is FooId - it's a part of Yesod's magic which I don't fully understand so far - it's generated automatically from the table definition - but it's a some kind of a number.
Because I don't know how to use MultiPiece I switched to simpler solution and modified:
route: /foos/#Int/#Int/#String FoosReturnR GET
handler: [added also some logging]
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
and now it is compiling but when I browse to: http://localhost:3000/sectors/1/1/1,2 I get a page containing only:
Internal Server Error
Prelude.read: no parse
Well, I don't fully understand what is FooId here - how to create such a list of FooId's from list of strings containing numbers?
And of course a solution of how to make the FooId an instance of MultiPiece is most wanted.
EDIT:
Daniel and svachalek, thanks for your posts - I tried your (Daniel's) solution but then I was receiving errors saying that [FooId] is expected (as in the handler function declaration) but FooId type was given and this lead me to the following solution:
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
of course I changed the route to: /foos/#Int/#Int/*FooIds FoosReturnR GET
and the handler to:
getFoosReturnR :: Int -> Int -> FooIds -> Handler RepPlain
getFoosReturnR coordX coordY (FooIds withoutIds) = do
and now I don't get any errors during compilation nor runtime, and the only not satisfying thing is that I always receive Not Found as a result, even if I supply parameters that should give me some results - so now I have to figure out how to determine what SQL was exactly sent to the database
EDIT:
Now I see that the "Not Found" is connected to the problem and that the above edit is not a solution - when I browse to localhost:3000/foos/4930000/3360000 then I get the results (but then the FooIds is empty) - but when I add something like: localhost:3000/sectors/4930000/3360000/1 then I always get "Not Found" - so it's still not working..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
希望我能提供帮助,但据我所知,yesod 与网络应用程序有关,因此我从未真正研究过它。所以我可以尝试在空中刺一下,也许我撞到了什么东西。
Hayoo 通向
Yesod.Dispatch
。由于FooId
似乎有一个Read
实例,并且可能有一个Show
实例,您可以尝试我不知道这是否接近正确的事情,我本来想把它作为评论发布的,但它太长了,而且评论中没有太多格式。如果它没有帮助,我将删除它,以免给人留下你的问题已经有答案的印象,而实际上它还没有答案。
Wish I could help, but yesod has something to do with web applications, as far as I know, hence I've never really looked at it. So I can just try a stab in the air, maybe I hit something.
Hayoo leads to
in
Yesod.Dispatch
. SinceFooId
seems to have aRead
instance and probably aShow
instance, you could tryI have no idea whether that is close to the right thing, and I would have posted it as a comment, but it's too long and there's not much formatting in comments. If it doesn't help I will delete it to not give the impression your question already has an answer when it hasn't.
问题已解决:)
您可以使用问题的最后编辑之一中的我的实现,然后浏览到如下 URL:
http://localhost:3000/foos/4930000/3360000/Key {unKey = PersistInt64 3 }/Key {unKey = PersistInt64 4}
Key 类型派生 Read 但不是以非常友好(和预期)的方式:)
或者将 fromMultiPiece 的实现更改为:
并使用类似以下的 URL:
http://localhost:3000/foos/4930000/3360000/1/ 2
非常感谢 Yesod Web Framework Google Group 的 David McBride
编辑:上述解决方案只有一个缺点 - 使用 PersistInt64 类型 - 它不是一个使用这样的实现细节是一种很好的做法,但可以通过使用
Database.Persist
中的fromPersistValue
和toPersistValue
函数来修复它,如下所示: ,也非常感谢大卫·麦克布莱德!
The problem is solved:)
You could either use my implementation from one of the last edits of the question and browse to URL like:
http://localhost:3000/foos/4930000/3360000/Key {unKey = PersistInt64 3}/Key {unKey = PersistInt64 4}
The Key type derives Read but not in a very friendly (and expected) way:)
Or change the implementation of fromMultiPiece to:
and use URLs like:
http://localhost:3000/foos/4930000/3360000/1/2
Many thanks to David McBride from the Yesod Web Framework Google Group
EDIT: the above solution had only one disadvantage - using the PersistInt64 type - it's not a good practice to use such a details of implementation, but it can be repaired by using
fromPersistValue
andtoPersistValue
functions fromDatabase.Persist
as follows:Again, big thanks to David McBride also for this!
我对 Yesod 也相当陌生,我屈服了并将 -XTypeSynonymInstances 添加到我的 .cabal 文件中的 ghc-options 中,到目前为止,它让我的生活变得更加轻松。我不确定这是否是对这个特定问题的最优雅的答案,但否则我预测您会经常遇到别名实例错误。 PS 尝试 id = (Key (PersistInt 64 n))
I'm also fairly new to Yesod and I gave in and added -XTypeSynonymInstances to the ghc-options in my .cabal file, and so far it's made life a lot easier for me. I'm not sure if it's the most elegant answer to this particular problem, but otherwise I predict you'll run into that instance-of-alias error pretty frequently. P.S. try id = (Key (PersistInt 64 n))