当前位置: 首页 > 软件库 > 游戏/娱乐 > >

dunai

授权协议 Readme
开发语言 Haskell
所属分类 游戏/娱乐
软件类型 开源软件
地区 不详
投 递 者 祁权
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Dunai

This repository implements a generalized version of reactive programming, ontop of which other variants like Yampa, Classic FRP and Reactive Values canbe implemented.

Installation

$ cabal update
$ cabal install --lib dunai

Dependencies

Dunai currently supports GHC versions 7.6.3 to 8.10.4.

Examples

Open a GHCi session and import the main Dunai module. If all goes well, weshould see no error messages:

$ ghci
ghci> import Data.MonadicStreamFunction

An MSF is a time-varying transformation applied to a series of inputs as theycome along, one by one.

Use the primitive arr :: (a -> b) -> MSF m a b to turn any pure function intoan MSF that applies the given function to every input. The function embed :: MSF m a b -> [a] -> m [b] runs an MSF with a series of inputs, collecting theoutputs:

ghci> embed (arr (+1)) [1,2,3,4,5]
[2,3,4,5,6]

MSFs can have side effects; hence the m that accompanies the type MSF inthe signatures of arr and embed. The function arrM turns a monadicfunction of type a -> m b into an MSF that will constantly apply thefunction to each input.

For example, the function print takes a value and prints it to the terminal(a side effect in the IO monad), producing an empty () output. Elevatingor lifting print into an MSF will turn it into a processor that prints eachinput passed to it:

ghci> :type print
print :: Show a => a -> IO ()
ghci> :type arrM print
arrM print :: Show a => MSF IO a ()

If we now run that MSF with five inputs, all are printed to the terminal:

ghci> embed (arrM print) [1,2,3,4,5]
1
2
3
4
5
[(), (), (), (), ()]

As we can see, after all side effects, embed collects all the outputs, whichGHCi shows at the end.

When we only care about the side effects and not the output list, we candiscard it with Control.Monad.void. (Dunai provides an auxiliary functionembed_ for the same purpose.)

ghci> import Control.Monad (void)
ghci> void $ embed (arrM print) [1,2,3,4,5]
1
2
3
4
5

MSFs can be piped into one another with the functions (>>>) or (.), so thatthe output of one MSF is fed as input to another MSF at each point:

ghci> void $ embed (arr (+1) >>> arrM print) [1,2,3,4,5]
2
3
4
5
6

A monadic computation without arguments can be lifted into an MSF with thefunction constM:

ghci> :type getLine
getLine :: IO String
ghci> :type constM getLine
constM getLine :: MSF IO a String

This MSF will get a line of text from the terminal every time it is called,which we can pipe into an MSF that will print it back.

ghci> void $ embed (constM getLine >>> arrM putStrLn) [(), ()]
What the user types, the computer repeats.
What the user types, the computer repeats.
Once again, the computer repeats.
Once again, the computer repeats.

Notice how we did not care about the values in the input list to embed: theonly thing that matters is how many elements it has, which determines how manytimes embed will run the MSF.

Simulations can run indefinitely with the function reactimate :: MSF m () () -> m (), which is useful when the input to the MSFs being executed is beingproduced by another MSFs, like in the case above with constM getLineproducing inputs consumed by arrM putStrLn:

ghci> reactimate (constM getLine >>> arr reverse >>> arrM putStrLn)
Hello
olleH
Haskell is awesome
emosewa si lleksaH
^C

Dunai has a very extensive API and supports many programming styles. MSFs areapplicatives, so we can transform them using applicative style, and they arecategories, so they can be piped into one another with Control.Category.(.).For example, the line above can also be written as:

ghci> reactimate (arrM putStrLn . (reverse <$> constM getLine))

which is equivalent to:

ghci> reactimate (arrM putStrLn . fmap reverse . constM getLine)

Other writing styles (e.g., arrow notation) are also supported. Thisversatility makes it possible for you to use the notation you feel mostcomfortable with.

MSFs are immensely expressive. With MSFs, you can implement stream programming,functional reactive programming (both classic and arrowized), reactiveprogramming, and reactive values, among many others. The real power of MSFscomes from the ability to carry out temporal transformations (e.g., delays), toapply different transformations at different points in time, and to work withdifferent monads. See the documentation below to understand how capable theyare.

Further references

Reading

The best introduction to the fundamentals of Monadic Stream Functions is:

The following papers are also related to MSFs:

Video

Games

  • The Bearriver Arcade. Fun arcade games made using bearriver.
  • Haskanoid. Haskell breakout game implemented using the Functional Reactive Programming library Yampa (compatible with Dunai/Bearriver).

Structure and internals

This project is split in three parts:

  • Dunai: a reactive library that combines monads and arrows.
  • BearRiver: Yampa implemented on top of Dunai.
  • Examples: ballbounce
    • sample applications that work both on traditional Yampa and BearRiver.

We need to add examples of apps written in classic FRP, reactive values, etc.The game haskanoid works bothwith Yampa and with Bearriver/dunai.

Performance

Performance is ok, simpler games will be playable without furtheroptimisations. This uses unaccelerated SDL 1.2. The speed is comparable toYampa's.

2016-05-09 15:29:41 dash@dash-desktop:~/Projects/PhD/Yampa/yampa-clocks-dunai$ ./.cabal-sandbox/bin/haskanoid

Performance report :: Time per frame: 13.88ms, FPS: 72.04610951008645, Total running time: 1447
Performance report :: Time per frame: 16.46ms, FPS: 60.75334143377886, Total running time: 3093
Performance report :: Time per frame: 17.48ms, FPS: 57.20823798627002, Total running time: 4841
Performance report :: Time per frame: 19.56ms, FPS: 51.12474437627812, Total running time: 6797
Performance report :: Time per frame: 19.96ms, FPS: 50.100200400801604, Total running time: 8793
Performance report :: Time per frame: 19.44ms, FPS: 51.440329218106996, Total running time: 10737

It runs almost in constant memory, with about 50% more memory consumption thanwith Yampa (200k for Yampa and 300K for dunai/bearriver). There is very minorleaking, probably we can fix that with seq.

We have obtained different figures tracking different modules. In the paper, weprovided figures for the whole game, but we need to run newer reliablebenchmarks including every module and only things that live in FRP.Yampa,FRP.BearRiver and Data.MonadicStreamFunction.

You can try it with:

git clone https://github.com/ivanperez-keera/haskanoid.git
cd haskanoid/
cabal install -f-wiimote -f-kinect -fbearriver

Related Projects

ivanperez-keera/Yampa

turion/rhine

Contributions

We follow: http://nvie.com/posts/a-successful-git-branching-model/

Feel free to open new issues. We are looking for:

  • Unexplored ways of using MSFs.
  • Other games or applications that use MSFs (including but not limited to Yampa games).
  • Fixes. The syntax and behaviour are still experimental. If somethingbreaks/sounds strange, please open an issue.

About the name

Dunai (aka. Danube, or Дунай) is one of the main rivers in Europe, originatingin Germany and touching Austria, Slovakia, Hungary, Croatia, Serbia, Romania,Bulgaria, Moldova and Ukraine.

Other FRP libraries, like Yampa, are named after rivers. Dunai has been chosendue to the authors' relation with some of the countries it passes through, andknowing that this library has helped unite otherwise very different people fromdifferent backgrounds.

  • Problem - A - Codeforces 题目大意:现给出前n届TI(dota2国际邀请赛)的冠军队伍名单,他们分别负责1到5号位,然后给出m个下一届TI的候选选手名单,组队的规则是五个人必须每人承担1-5号位,且必须至少有一人拿过冠军,问最多能组成多少队伍 1<=n<=100;1<=m<=1000 思路:因为要求每支队伍中至少有一个冠军,所以我们可以从冠军入手,给冠军匹配队友,所以我们先

相关阅读

相关文章

相关问答

相关文档