有一天我很无聊,想锻炼我的大脑,所以我决定做99个Haskell问题但是限制自己以无点的方式做这些.当我以无点样式执行操作时,似乎出现了很多问题:如何将多个函数应用于相同的值,同时将每个结果保持为独立实体?使用尖头符号:
foobar x = [id x, reverse x]
Run Code Online (Sandbox Code Playgroud)
到目前为止我用无点符号得出了什么:
foobar' = `map` [id, reverse] ($ x)
Run Code Online (Sandbox Code Playgroud)
我似乎无法x
在那里结束.
我正在尝试使用Haskell和Pipes库实现一个简单的Web服务器.我现在明白管道不可能使用循环或钻石拓扑,但我认为我想要的是.因此我想要的拓扑结构是:
-GET--> handleGET >-> packRequest >-> socketWriteD
|
socketReadS >-> parseRequest >-routeRequest
|
-POST-> handlePOST >-> packRequest >-> socketWriteD
Run Code Online (Sandbox Code Playgroud)
我有HTTPRequest RequestLine Headers Message
和HTTPResponse StatusLine Headers Message
链中使用的类型.socketReadS
从套接字中获取字节并将它们转发给它parseRequest
,它使用Attoparsec将字节解析为一个HTTPRequest
对象.然后,我希望管道分支至少两次,可能更多,具体取决于我实现的HTTP方法数量.每个handle<method>
函数都应该接收HTTPRequest
来自上游和前向HTTPResponse
对象的对象packRequest
,这些对象只是将HTTPResponse对象打包成一个ByteString
随时可以发送的对象socketWriteS
.
如果我让GHC推断出类型,那么下面的代码可以检查routeRequest'''
(我的某种方式似乎有些偏差).但是之后似乎没有任何事情在执行parseRequest
.任何人都可以帮我找出原因吗?
我有以下代码routeRequest
应该处理分支.
routeRequest''' ::
(Monad m, Proxy p1, Proxy p2, Proxy p3)
=> () -> Consumer p1 HTTPRequest (Pipe p2 HTTPRequest HTTPRequest (Pipe p3 …
Run Code Online (Sandbox Code Playgroud) 我无法理解Haskell中镜头库的所有细微差别.
假设我有以下镜头
activePlayer :: Lens' Game Player
activePlayer = lens get set
where
get (Game {_players = (index, seq) }) = S.index seq index
set g@(Game {_players = (index, seq) }) player =
g { _players = (index, S.update index player seq) }
Run Code Online (Sandbox Code Playgroud)
在ghci提示符下执行以下操作没有问题:
> :t do{use (activePlayer); activePlayer.= undefined}
:: Control.Monad.State.Class.MonadState Game m => m ()
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试将其参数化为函数时,我得到以下错误.
> :t \p -> do{use p; p.=undefined}
<interactive>:1:17:
Couldn't match type `Accessor a0 a0' with `Mutator b0'
Expected type: ASetter s0 s0 …
Run Code Online (Sandbox Code Playgroud) 我正在为一个相当复杂的视频游戏做一些概念验证工作,我想使用HOpenGL库在Haskell中编写.我开始编写一个实现基于客户端 - 服务器事件的通信的模块.当我尝试将其连接到一个简单的程序以在屏幕上绘制点击时,我的问题出现了.
事件库使用TChans列表作为优先级队列进行通信.它返回一个"out"队列和一个对应于服务器绑定和客户端绑定消息的"in"队列.发送和接收事件使用forkIO在单独的线程中完成.在没有OpenGL部分的情况下测试事件库表明它成功通信.这是我用来测试它的代码:
-- Client connects to server at localhost with 3 priorities in the priority queue
do { (outQueue, inQueue) <- client Nothing 3
-- send 'Click' events until terminated, the server responds with the coords negated
; mapM_ (\x -> atomically $ writeThing outQueue (lookupPriority x) x)
(repeat (Click (fromIntegral 2) (fromIntegral 4)))
}
Run Code Online (Sandbox Code Playgroud)
这会产生预期的输出,即大量的发送和接收事件.我认为问题不在于事件处理库.
代码的OpenGL部分检查传入队列中displayCallback中的新事件,然后调用事件的关联处理程序.我可以得到一个事件(Init事件,它只是清除屏幕)被displayCallback捕获,但之后没有任何事情被捕获.这是相关的代码:
atomically $ PQ.writeThing inqueue (Events.lookupPriority Events.Init) Events.Init
GLUT.mainLoop
render pqueue =
do event <- atomically $
do e <- PQ.getThing pqueue …
Run Code Online (Sandbox Code Playgroud) 我有以下代码.我希望能够在给定游戏状态时修改活动玩家的生命.我想出了一个activePlayer
镜头,但当我尝试将它与-=
操作员结合使用时,我收到以下错误:
> over (activePlayer.life) (+1) initialState
<interactive>:2:7:
No instance for (Contravariant Mutator)
arising from a use of `activePlayer'
Possible fix:
add an instance declaration for (Contravariant Mutator)
In the first argument of `(.)', namely `activePlayer'
In the first argument of `over', namely `(activePlayer . life)'
In the expression: over (activePlayer . life) (+ 1) initialState``
Run Code Online (Sandbox Code Playgroud)
和有问题的代码:
{-# LANGUAGE TemplateHaskell #-}
module Scratch where
import Control.Lens
import Control.Monad.Trans.Class
import Control.Monad.Trans.State
import Data.Sequence (Seq)
import qualified Data.Sequence as …
Run Code Online (Sandbox Code Playgroud) 所以我一直听到很多关于点自由编程的知识,我决定做一个小实验来测试我对它的掌握程度.这涉及采用有针对性的函数来计算数字的阶乘并将其转换为无点形式.我设法做到了,但是无点结果的可读性远远低于尖锐的结果.
-- pointed
fact 0 = 1
fact n = n * (fact (n-1))
-- point free
fact' = foldr1 (*) . takeWhile ((<) 0) . iterate (flip (-) 1)
Run Code Online (Sandbox Code Playgroud)
我是否遗漏了指向自由符号所必需的东西,或者这是否可以像某些转换那样可读?对我来说,似乎fact
函数的很大一部分是零上的模式匹配,实际上,模式匹配是我喜欢Haskell的最大原因之一.然而,无点符号似乎完全不允许这一点,以及其他一些非常有用的东西,如列表推导.
在Haskell中,forkIO创建一个未绑定(Haskell)线程,forkOS创建一个绑定(本机)线程.这里的前一个问题的答案我已经提到Haskell线程不能保证保持在同一个OS线程上,这似乎得到了Control.Concurrent模块文档的支持.我的问题是,如果正在运行的Haskell线程被交换到另一个OS线程,它的ThreadID是否会保持不变?
我试图创建一些看起来很像State monad的东西,但是它还带有一个谓词列表和相应的状态转换函数.我想象的计算的基本步骤如下:
Foo (state, [(pred, t)]) >>= f
.适用f
于s
,产生s'
.然后将每个谓词应用于s'
.对于匹配的每个谓词,将关联的转换函数按顺序应用于状态.例如,假设[(p1, t1), (p2, t2), (p3, t3)]
,f
和s
.如果在f s
收益率之后s'
,p1 s'
并且p3 s'
两者都返回True
,那么你将执行t1 s'
屈服s''
,然后执行t3 s''
屈服s'''
,即计算的结果.
这里有很多移动部件,我觉得正确的方法是在StateT变换器或State monad之上构建它,但是我无法弄清楚从哪里开始.
我觉得好像这不是很清楚.任何澄清会使这个更清楚,非常感谢.
haskell ×9
concurrency ×2
haskell-lens ×2
pointfree ×2
cabal ×1
hunit ×1
opengl ×1
state-monad ×1
unit-testing ×1