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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
590
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
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
350
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
180
新卒PdEのリアル
ryu1013
1
500
What We Talk About When We Talk About XP
m_seki
2
630
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
190
Family mrubyの進捗
kishima
1
120
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
170
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
490
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
7.2k
一参加者から『中の人』へ 〜全通PHPerがブースに立って学んだ、カンファレンスを100倍楽しむコツ〜
wp_daisuke
0
160
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
120
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
480
Featured
See All Featured
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
810
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1k
Ruling the World: When Life Gets Gamed
codingconduct
0
330
Navigating Weather and Climate Data
rabernat
0
520
Thoughts on Productivity
jonyablonski
76
5.4k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
HDC tutorial
michielstock
2
870
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
A Soul's Torment
seathinner
8
3.6k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
740
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
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!