Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
A Brief Introduction to Dialyzer and Proper
Search
Christopher Meiklejohn
February 02, 2014
Programming
150
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
A Brief Introduction to Dialyzer and Proper
Christopher Meiklejohn
February 02, 2014
More Decks by Christopher Meiklejohn
See All by Christopher Meiklejohn
Towards a Solution to the Red Wedding Problem
cmeiklejohn
0
450
Language Support for Cloud-Scale Distributed Systems
cmeiklejohn
0
600
Towards a Systems Approach to Distributed Programming
cmeiklejohn
3
410
Scaling a Startup with a 21st Century Programming Language
cmeiklejohn
0
440
Practical Evaluation of the Lasp Programming Model at Scale
cmeiklejohn
4
2.9k
Just-Right Consistency - Closing the CAP Gap
cmeiklejohn
3
330
Declarative, Convergent, Edge Computation
cmeiklejohn
1
250
Just-Right Consistency - Closing the CAP Gap
cmeiklejohn
3
1.4k
A Certain Tendency of the Database Community
cmeiklejohn
0
500
Other Decks in Programming
See All in Programming
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
250
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
400
Verilogで学ぶCPU自作入門.pdf
uyuki234
7
3.8k
Androidだけじゃない、DroidKaigiで広がった私の技術スタック
akkeylab
0
100
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
3.1k
カツオ、ご期待ください
suneo3476
0
120
AHC070解法紹介
eijirou
0
140
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
600
巨大モノリシックアプリ モダン化大作戦
ktcryomm
1
1.2k
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
430
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
310
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
190
Featured
See All Featured
Building Adaptive Systems
keathley
44
3.2k
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
エンジニアに許された特別な時間の終わり
watany
109
250k
Un-Boring Meetings
codingconduct
0
430
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
From π to Pie charts
rasagy
1
380
Scaling GitHub
holman
464
140k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
1
610
ラッコキーワード サービス紹介資料
rakko
1
5.1M
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
290
Transcript
Dialyzer / PropEr Christopher Meiklejohn Basho Technologies, Inc.
Static analysis tool for Erlang Dialyzer
Based on success typings Dialyzer
-opaque gcounter() :: orddict:orddict(). ! -type gcounter_op() :: increment |
{increment, pos_integer()}. ! %% @doc Create a new, empty `gcounter()' -spec new() -> gcounter(). new() -> orddict:new(). ! %% @doc Create a `gcounter()' with an initial update -spec new(term(), pos_integer()) -> gcounter(). new(Id, Count) when is_integer(Count), Count > 0 -> {ok, Cnt} = update({increment, Count}, Id, new()), Cnt.
%% @doc Create a `gcounter()' with an initial update -spec
new(term(), atom()) -> gcounter(). new(Id, Count) when is_integer(Count), Count > 0 -> {ok, Cnt} = update({increment, Count}, Id, new()), Cnt.
riak_dt_gcounter.erl:63: Invalid type specification for function riak_dt_gcounter:new/2. The success typing
is (_,pos_integer()) -> riak_dt_gcounter:gcounter()
%% @doc Create a `gcounter()' with an initial update -spec
new(riak_dt:actor(), pos_integer()) -> gcounter(). new(Id, Count) when is_integer(Count), Count > 0 -> {ok, Cnt} = update({increment, Count}, Id, new()), Cnt. ! %% @doc `increment' the entry in `GCnt' for `Actor' by 1 or `{increment, Amt}'. %% returns an updated `gcounter()' or error if `Amt' is not a `pos_integer()' -spec update(gcounter_op(), riak_dt:actor(), gcounter()) -> {ok, gcounter()}. update(increment, Actor, GCnt) -> {ok, increment_by(1, Actor, GCnt)}; update({increment, Amount}, Actor, GCnt) when is_integer(Amount), Amount > 0 -> {ok, increment_by(Amount, Actor, GCnt)}.
riak_dt_gcounter.erl:64: Function new/2 has no local return riak_dt_gcounter.erl:65: The call
riak_dt_gcounter:update({'incremet',pos_integer()},Id::any(),riak_dt_g counter:gcounter()) breaks the contract (gcounter_op(),riak_dt:actor(),gcounter()) -> {‘ok',gcounter()}
%% @doc Create a `gcounter()' with an initial update -spec
new(riak_dt:actor(), pos_integer()) -> gcounter(). new(Id, Count) when is_integer(Count), Count > 0 -> {ok, Cnt} = update({increment, Count}, Id, new()), Cnt. ! %% @doc `increment' the entry in `GCnt' for `Actor' by 1 or `{increment, Amt}'. %% returns an updated `gcounter()' or error if `Amt' is not a `pos_integer()' -spec update(gcounter_op(), riak_dt:actor(), gcounter()) -> {ok, gcounter()}. update(increment, Actor, GCnt) -> {ok, increment_by(1, Actor, GCnt)}.
riak_dt_gcounter.erl:64: Function new/2 has no local return riak_dt_pncounter.erl:216: The created
fun has no local return
Demo
Property-based testing tool PropEr
Inspired by QuickCheck; licensed under GPL PropEr
Full integration with Erlang specifications PropEr
Simple
-module(simple_props). ! %% Properties are automatically exported. -include_lib("proper/include/proper.hrl"). ! %%
Functions that start with prop_ are considered properties prop_t2b_b2t() -> ?FORALL(T, term(), T =:= binary_to_term(term_to_binary(T))).
1> c(simple_props). {ok,simple_props} 2> proper:quickcheck(simple_props:prop_t2b_b2t()). ................................................... ................................................. OK: Passed 100
test(s) true
Stack
-spec new() -> stack(_T). new() -> {0, []}. ! -spec
push(T, stack(T)) -> stack(T). push(X, {N,Elems}) -> {N+1, [X|Elems]}. ! -spec pop(stack(T)) -> {T,stack(T)}. pop({0, []}) -> throw(stack_empty); pop({N, [Top|Rest]}) when N > 0 -> {Top, {N-1,Rest}}.
prop_push_pop() -> ?FORALL({X,S}, {integer(),stack(integer())}, begin {Y,_} = pop(push(X,S)), X =:=
Y end).
Eshell V5.10.3 (abort with ^G) 1> proper:quickcheck(stack:prop_push_pop()). ...................................................................... .............................. OK:
Passed 100 test(s). true
Lists
prop_reverse() -> ?FORALL(X, list(integer()), lists:reverse(lists:reverse(X)) == X).
7> proper:quickcheck(lists_proper:prop_reverse()). ...................................................................... .............................. OK: Passed 100 test(s). true
prop_delete() -> ?FORALL(L, non_empty(list(integer())), ?FORALL(X, elements(L), not lists:member(X, (lists:delete(X, L))))).
16> proper:quickcheck(lists_proper:prop_delete()). ........! Failed: After 9 test(s). [-1,-1] -1 !
Shrinking (0 time(s)) [-1,-1] -1 false 17>
17> proper:quickcheck(lists_proper:prop_delete()). ..................................! Failed: After 35 test(s). [2,-10,-7,13,70,2] 2 !
Shrinking ......(6 time(s)) [2,2] 2 false
prop_delete() -> ?FORALL(L, non_empty(list(integer())), ?FORALL(X, elements(L), lists:foldl(fun(Y, Acc) -> case
Y of X -> Acc + 1; _ -> Acc end end, 0, L) - 1 == lists:foldl(fun(Y, Acc) -> case Y of X -> Acc + 1; _ -> Acc end end, 0, lists:delete(X, L)))).
22> proper:quickcheck(lists_proper:prop_delete()). ...................................................................... .............................. OK: Passed 100 test(s). true
Thanks!