似乎newtype
定义只是data
遵循某些限制的定义(例如,只有一个构造函数),并且由于这些限制,运行时系统可以newtype
更有效地处理s.并且未定义值的模式匹配处理略有不同.
但是假设Haskell只知道data
定义,没有newtype
s:编译器不能自己发现给定的数据定义是否遵守这些限制,并自动更有效地对待它?
我确定我错过了什么,必须有更深层次的理由.
我无法弄清楚"| m - > w"-part在类定义中意味着什么:
class (Monoid w, Monad m) => MonadWriter w m | m -> w
Run Code Online (Sandbox Code Playgroud)
这增加了什么附加信息给类定义?
在我的业务领域 - 金融机构的后台IT - 软件组件通常进行全局配置,记录其进度,进行某种错误处理/计算短路是很常见的...可以通过Haskell中的Reader-,Writer-,Maybe-monads等很好地建模,并与monad变换器一起组合.
但似乎存在一些缺点:monad变换器背后的概念非常棘手且难以理解,monad变换器导致非常复杂的类型签名,并且它们会造成一些性能损失.
所以我想知道:monad变形金刚在处理上述常见任务时是最佳做法吗?
我想知道为什么
Prelude> head $ reverse $ [1..10000000] ++ [99]
99
Run Code Online (Sandbox Code Playgroud)
不会导致堆栈溢出错误.前奏中的++似乎是直接的,非尾递归的:
(++) :: [a] -> [a] -> [a]
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys
Run Code Online (Sandbox Code Playgroud)
编辑:最初,我认为这个问题与前奏中定义的++的方式有关,特别是对于重写规则,因此问题继续如下.讨论向我表明情况并非如此.我现在认为一些懒惰的评估效果导致代码在没有堆栈溢出的情况下运行,但我不太明白如何.
所以就这样,它会遇到堆栈溢出,对吧?所以我认为它可能与遵循++定义的ghc魔法有关:
{ - #RULES"++"[~1] forall xs ys.xs ++ ys = augment(\ cn - > foldr cn xs)ys# - }
*这有助于避免堆栈溢出吗?有人可以提供一些暗示这段代码中发生了什么吗?**
我正在设计一个小型足球游戏,其中游戏引擎(计算玩家移动等)在服务器上运行,并且渲染和键盘/鼠标处理由客户端完成.对于我想要使用的服务器(Haskell)
每20ms左右,客户端应通过HTTP GET向服务器发送键盘和鼠标事件,接收当前游戏状态(JSON编码的球和玩家位置)并渲染它.我正在考虑将SDL基础设施用于游戏循环,输入处理和渲染.
服务器基本上运行两个线程:一个happstack服务器接收HTTP GET,将键盘/鼠标命令放入队列,从第二个队列读取当前游戏状态并回答HTTP GET请求.
第二个线程运行Yampa游戏引擎,如Yampa Arcade论文中所述:游戏引擎尽可能快地计算新一轮(无滴答)并将结果放入渲染队列.
一般问题:这看起来像一个可行的架构吗?
具体问题:如何设计服务器端渲染队列:是否会使用Chan进行此操作?如果游戏引擎的平均速度比客户端的"滴答"快,则队列将变得越来越长.怎么可以用Chan处理?
非常欢迎您的意见!
我正试图用Yampa-Framework模拟一个弹跳球:给定一个初始的x位置,高度和速度,球应该根据重力规则弹跳.信号功能以"提示 - 事件"作为输入,这个想法是"当球被倾斜时,它的速度应该加倍".
球反弹很好,但每次有小费事件时,该功能都会进入无限循环.我想我可能需要添加一个延迟(dSwitch,pre,notYet?),但我不知道如何.任何帮助,将不胜感激!
{-# LANGUAGE Arrows #-}
module Ball where
import FRP.Yampa
type Position = Double
type Velocity = Double
type Height = Double
data Ball = Ball {
height :: Height,
width :: Position,
vel :: Velocity
} deriving (Show)
type Tip = Event ()
fly :: Position -> (Height, Velocity) -> SF Tip (Ball, Event (Height,Velocity))
fly w0 (h0, v0) = proc tipEvent -> do
let tip = (tipEvent == Event ())
v <- (v0+) ^<< integral …
Run Code Online (Sandbox Code Playgroud) 像这样的简单追加函数(在F#中):
let rec app s t =
match s with
| [] -> t
| (x::ss) -> x :: (app ss t)
Run Code Online (Sandbox Code Playgroud)
当s变大时会崩溃,因为函数不是尾递归的.我注意到F#的标准追加功能不会因大列表而崩溃,因此必须以不同方式实现.所以我想知道:追尾的尾递归定义怎么样?我提出了这样的事情:
let rec comb s t =
match s with
| [] -> t
| (x::ss) -> comb ss (x::t)
let app2 s t = comb (List.rev s) t
Run Code Online (Sandbox Code Playgroud)
哪个有效,但看起来很奇怪.是否有更优雅的定义?
有没有一种很好的方法可以在列表中找到第一次出现的构造函数,而下面的示例中没有显式的递归?
data Elem = A Int | B Char deriving Show
getA :: [Elem] -> Maybe Elem
getA [] = Nothing
getA (e:es) =
case e of
A a -> Just (A a)
_ -> getA es
Run Code Online (Sandbox Code Playgroud) 我为一个我正在工作的小足球比赛写了一个有限状态机模块.它提供了一个用于设置FSM的接口(基本上是它的状态和转换).对于每个状态,您可以提供将在进入和退出时触发的函数,或者当FSM保持相同状态时,这些函数然后返回一些消息.它还提供了一个反应接口(Yampa),它产生时变状态并收集随时间发生的消息.该代码是在这里数据/ FSM.hs.
我正在寻找一种测试这个模块的好方法.由于它是纯净的,我想考虑快速检查一下.我没有经验快速检查,所以任何提示将不胜感激!到目前为止我的基本理解是:一个人会提供一些或多或少随机构建FSM的函数,然后在它们上运行一些(或多或少随机)转换.但我不太明白如何以这种方式构建测试......
所以我现在正在写这个小小的足球比赛一段时间了,有一件事从一开始就让我感到困惑.游戏遵循Yampa Arcade模式,因此游戏中的"对象"有一个总和类型:
data ObjState = Ball Id Pos Velo
| Player Id Team Number Pos Velo
| Game Id Score
Run Code Online (Sandbox Code Playgroud)
对象对消息做出反应,因此还有另一种和类型:
data Msg = BallMsg BM
| PlayerMsg PM
| GameMsg GM
data BM = Gained | Lost
data PM = GoTo Position | Shoot
data GM = GoalScored | BallOutOfBounds
Run Code Online (Sandbox Code Playgroud)
Yampa框架依赖于所谓的信号功能.在我们的例子中,有球,球员和比赛行为的信号功能.粗略简化:
ballObj, playerObj, gameObj :: (Time -> (GameInput, [Msg]))
-> (Time -> (ObjState, [(Id, Msg)]))
Run Code Online (Sandbox Code Playgroud)
所以例如ballObj在任何给定时间采用一个产生GameInput(击键,游戏状态......)和一个专门用于球的消息列表的函数,并返回一个产生球状态的函数和它给其他对象的消息(球,比赛,球员)在任何给定的时间.在Yampa,类型签名实际上看起来更好一些:
ballObj, playerObj, gameObj :: SF (GameInput, [Msg]) (ObjState, [(Id, …
Run Code Online (Sandbox Code Playgroud) haskell ×9
frp ×3
types ×2
append ×1
concurrency ×1
f# ×1
game-engine ×1
ghc ×1
monads ×1
quickcheck ×1
syntax ×1
testing ×1
type-systems ×1
typeclass ×1