Hamler 0.2 正式发布,基于 Erlang 与 Haskell 的编程语言
我们在这里很高兴地和大家分享 Hamler 0.2 版本发布的消息!
Hamler 是一门构建在 Erlang 虚拟机(VM)上的 Haskell 风格的强类型(Strongly-typed)编程语言,独特地结合了编译时的类型检查推导,与对运行时高并发和软实时能力的支持。
Hamler 0.2 现已支持大部分 Erlang 的并发编程特性,包括基于 Actor Model 的 Message Passing Concurrency 和 OTP Behaviours。
关于 Actor Model
1974年,卡尔-休伊特教授发表了论文《Actor model of computation》。文中,他阐述了 Actor 作为一个计算实体,它会对收到的消息作出回应,并可以并发地进行以下操作:
- 向其他 Actor 发送有限数量的消息
- 创建有限数量的新 Actor
- 指定下一个收到的消息所要使用的行为
随着多核计算和大规模分布式系统的兴起,Actor 模型因其天然的并发性、并行性和分布式变得越来越重要。
Process and Mailbox
Hamler/Erlang 中的 Actor 被定义为一个进程,它的工作方式就像一个 OS 进程。每个进程都有自己的内存,由一个 Mailbox、一个 Heap、一个 Stack 和一个包含进程信息的 Process Control Block(PCB) 组成。
Erlang 中的进程是非常轻量的,我们可以在一个正在运行的 Erlang 虚拟机上快速创建数百万个进程。
Message Passing Concurrency
“Message passing concurrency(MPS)是两个或多个进程之间没有共享资源情况下的并发,它们通过仅传递消息进行通信。” Actor Model 就是 MPS 模型的一个实现。
参考资料:
Ping/Pong示例:
import Prelude import Control.Process (selfPid) go :: Process () go = do self <- selfPid pid <- spawn loop pid ! (self, :ping) receive :pong -> println "Pong!" pid ! :stop loop :: Process () loop = receive (from, :ping) -> do println "Ping!" from ! :pong loop :stop -> return ()
Receive … after示例:
go :: Process () go = do pid <- spawn recvAfter pid ! :foo recvAfter :: Process () recvAfter = receive :bar -> println "recv bar" after 1000 -> println "timeout"
Selective Receive 示例:
go :: Process () go = do pid <- spawn selectiveRecv pid ! :bar pid ! :foo selectiveRecv :: Process () selectiveRecv = do receive :foo -> println "foo" receive :bar -> println "bar"
OTP Behaviours
Hamler 采用类型类(TypeClass)实现 OTP Behaviour。
TypeClass 定义了具有类似 operation 的一组类型。在我们的实现中,使用 typeclass 来对不同 OTP Behaviour 的类型进行区分。通过为每个 Behavour 定义一个 typeclass 的方式,我们对这些 Behaviour 做了某种程度上的抽象,并在一定程度上增加了类型约束。
GenServer Behaviour
Generic Server Behaviour 是对 客户端-服务器 关系模型中服务器的抽象。如图所示,在该模型的服务器侧,所有的通用操作都可以被封装成为一个模块。与 Erlang 一样,Hamler 将其封装为 GenServer 的模块。不同的是在 Hamler 中 GenServer 由类型类进行定义,它所有的回调函数和参数都必须受到类型约束,它在具备 Erlang 的 gen_server
特性的同时,也保证了类型的安全。以 handleCall
和 handleCast
为例:
参考资料 Erlang gen_server Behaviour。
GenServer Typeclass
class GenServer req rep st | req -> rep, rep -> st, st -> req where handleCall :: HandleCall req rep st handleCast :: HandleCast req rep st
A simple Server Example
module Demo.Server ( start , inc , dec , query ) where import Prelude import Control.Behaviour.GenServer ( class GenServer , HandleCall , HandleCast , Init , startLinkWith , initOk , call , cast , noReply , reply , shutdown ) import System.IO (println) data Request = Inc | Dec | Query data Reply = QueryResult Integer data State = State Integer name :: Atom name = :server start :: Process Pid start = startLinkWith name (init 20) inc :: Process () inc = cast name Inc dec :: Process () dec = cast name Dec query :: Process Integer query = do QueryResult i <- call name Query return i instance GenServer Request Reply State where handleCall = handleCall handleCast = handleCast init :: Integer -> Init Request State init n = initOk (State n) handleCall :: HandleCall Request Reply State handleCall Query _from (State i) = do println "Call: Query" reply (QueryResult i) (State i) handleCall _req _from st = shutdown :badRequest st handleCast :: HandleCast Request Reply State handleCast Inc (State n) = do println "Cast: Inc" noReply $ State (n+1) handleCast Dec (State n) = do println "Cast: Dec" noReply $ State (n-1) handleCast _ st = noReply st
GenStatem Behaviour
GenStatem Behaviour 抽象了对于 事件驱动的有限状态机(Event-driven Finite State Machine) 中通用的操作。对于该类型的状态机来说,它以触发状态转换的事件作为输入,而在状态转换过程中执行的动作作为输出,并得到新的状态。其模型如下:
State(S) x Event(E) -> Actions(A), State(S')
与 Erlang 中的实现类似,Hamler 使用 GenStatem 类型类对此状态机的通用操作进行封装。在 GenStatem
中仅提供一个事件处理的回调函数。其声明如下:
class GenStatem e s d | e -> s, s -> d, d -> e where handleEvent :: HandleEvent e s d
CodeLock FSM Example
module Demo.FSM.CodeLock ( name , start , push , stop ) where import Prelude import Control.Behaviour.GenStatem ( class GenStatem , Action(..) , EventType(..) , Init , OnEvent , initOk , handleWith , unhandled ) import Control.Behaviour.GenStatem as FSM data Event = Button Integer | Lock data State = Locked | Opened data Data = Data { code :: [Integer] , length :: Integer , buttons :: [Integer] } instance Eq State where eq Locked Locked = true eq Opened Opened = true eq _ _ = false instance GenStatem Event State Data where handleEvent = handleWith [(Locked, locked), (Opened, opened)] name :: Atom name = :code_lock start :: [Integer] -> Process Pid start code = FSM.startLinkWith name (init code) push :: Integer -> Process () push n = FSM.cast name (Button n) stop :: Process () stop = FSM.stop name init :: [Integer] -> Init Event State Data init code = initOk Locked d where d = Data $ { code = reverse code , length = length code , buttons = [] } locked :: OnEvent Event State Data locked Cast (Button n) (Data d) = let buttons = take d.length [n|d.buttons] in if buttons == d.code then let actions = [StateTimeout 1000 Lock] in FSM.nextWith Opened (Data d{buttons = []}) actions else FSM.keep (Data d{buttons = buttons}) locked t e d = unhandled t e Locked d opened :: OnEvent Event State Data opened Cast (Button _) d = FSM.keep d opened Timeout Lock d = do println "Timeout Lock" FSM.next Locked d opened t e d = unhandled t e Opened d
Supervisor Behaviour
Supervisor Behaviour 抽象了进程间容错的通用操作,它作为一个特殊的进程,以 监督者(Supervisor) 的角色管理其子进程,并在出现异常时重启相关的子进程,以提高系统的容错能力。
在 Hamler 中,这类行为被封装为 Supervisor 的类型类,并提供一个 init
回调函数来配置监督者的行为和子进程列表。这里的实现与 Erlang 中的 supervisor
是一致的。
Supervision Tree
监督者可以监控上文提到的 GenServer
或 GenStatem
生成的进程,同样也可以监控另外一个监督者。这便构成了 监控树(Supervision Tree)。如下图所示:
其中矩形表示一个监督者,圆表示一个工作者(它可以是一个 GenServer,GenStatem 或其它任意的进程)。当有进程异常退出时,监督者会按回调函数中配置的方式进行重启,例如:
- ‘1’ 表示
one_for_one
:仅重启异常退出的子进程。 - ‘a’ 表示
one_for_all
:重启该监督者下所有的子进程。
参考资料:Supervision Principles ,Erlang Supervisor Behaviour
A Supervisor Example
module Demo.Sup (start) where import Prelude import Demo.Event as Event import Demo.Server as Server import Demo.FSM.PushButton as FSM import Control.Behaviour.Supervisor ( Init , initOk , Strategy(..) , childSpec , startSupWith ) name :: Atom name = :sup start :: Process Pid start = startSupWith name init init :: Init init = initOk (OneForOne, 10, 100) [ childSpec "Demo.Event" Event.start , childSpec "Demo.Server" Server.start , childSpec "Demo.Statem" FSM.start ]
欢迎加入 Hamler 编程语言社区
Hamler 函数编程语言从发起即是一个开源项目,项目托管在 GitHub: https://github.com/hamler-lang/ 。 Hamler 目前由 EMQ - 杭州映云科技有限公司 研发团队主导开发,计划在 2020 年底前发布 0.5 版本用于 EMQ X 6.0 的开发。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
MeEdu v3.3 版本上线,在线教育点播系统
本次更新内容如下: 新增 added: 用户登录记录存储 added: 单点登录(不限制,单平台限制,全平台限制。平台有: PC,H5,ANDROID,IOS,MINI) added: 首页导航active routes added: 全局自定义css(PC和H5分开定义) added: 后台远程图片一键同步到本地 added: 幻灯片增加平台字段(pc,h5,mini,android,ios),不同平台读取所在平台的幻灯片 added: 微信小程序一键登录api(手机号一键登录) added: 课程列表增加免费课程过滤 优化 Laravel从5.8升级到6.x 单元测试phpunit升级到8.x 更换zip解压缩依赖(原先的zip扩展包已停止维护) 课程列表显示价格和课程订阅人数 优化注册流程字段,去掉了昵称和再次输入密码,使得注册更加方便 优化登录后的跳转 更新cors跨域扩展包 安装文档更新 优化后台敏感配置为空的情况下不显示*符号 修复 fixed: 微信小程序支付 fixed: 视频详情api接口的课程订阅数量统计 Github:https://github.com/Qsnh...
- 下一篇
SaaS 模式云数据仓库 MaxCompute 数据安全最佳实践
本文作者 阿里云智能 项目管理专家 王璀 什么是 MaxCompute? MaxCompute 是一款云原生、高效能的SaaS模式企业级数据仓库服务,被广泛用于构建现代化企业数据平台,开展BI分析、数据化运营、画像及推荐、智能预测等应用场景。 MaxCompute 构建在阿里云大规模计算、存储资源之上,以Serverless架构提供全托管的在线数据仓库服务,消除了传统数据平台在资源扩展性和弹性方面的限制,并最小化用户的运维投入。 MaxCompute支持多种经典计算模型(批处理、机器学习、交互式分析等)和完善的企业管理功能,借助MaxCompute,用户可轻松集成和管理企业数据资产,简化数据平台架构,加速价值实现。 MaxCompute 企业级安全能力升级 MaxCompute 近期对产品的安全能力进行了全面升级。 发布的安全能力有: · 细粒度授权· 数据加密 (BYOK)· 数据脱敏(数据保护伞)· 持续备份恢复· 跨地域的容灾备份· 实时审计日志 MaxCompute 安全体系 对于一个企业级的大数据平台,要应对的安全风险,有三个层次(如图-1):1.基础安全与可信平台,保障数据...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS关闭SELinux安全模块
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Windows10,CentOS7,CentOS8安装Nodejs环境
- 设置Eclipse缩进为4个空格,增强代码规范