# In lieu of a type system

**URL:** <https://swi-prolog.discourse.group/t/in-lieu-of-a-type-system/6666>\
**Category:** General\
**Tags:** discussion\
**Created:** [June 28, 2023, 8:24pm UTC](https://swi-prolog.discourse.group/t/in-lieu-of-a-type-system/6666 "2023-06-28T20:24:49Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![z5h](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/z5h/32/5445_2.png) [@z5h](https://swi-prolog.discourse.group/u/z5h)\
**Post date:** [June 28, 2023, 8:24pm UTC](https://swi-prolog.discourse.group/t/in-lieu-of-a-type-system/6666/1 "2023-06-28T20:24:49Z")

</div>

I’m not suggesting Prolog needs a type system.

But in some cases where I have unruly states to track, I’d like some of the peace of mind one gets with type inference, completeness checks, etc.

It occurred to me that the `domain` example at [Attributed variables](https://www.swi-prolog.org/pldoc/man?section=attvar) gives a foundation of a “poor man’s type checker”.

After some minor changes:

```prolog
domain(X, Dom) :-
        var(Dom), !,
        get_attr(X, domain, Dom).
domain(X, List) :-
        list_to_set(List, Domain),
        put_attr(Y, domain, Domain),
        X = Y.

% a sort of unified intersection
unisection(List1, List2, Set) :- 
    findall(X, (member(X,List1), member(X,List2)), List3), 
    list_to_set(List3, Set).

attr_unify_hook(Domain, Y) :-
        ( get_attr(Y, domain, Dom2)
        -> unisection(Domain, Dom2, NewDomain),
            ( NewDomain == []
            -> fail
            ; NewDomain = [Value]
            -> Y = Value
            ; put_attr(Y, domain, NewDomain)
            )
        ; var(Y)
        -> put_attr( Y, domain, Domain )
        ; member(Y, Domain)
        ).

```

Then we can have a domain-match-checker.

```prolog
is_maybe(Y) :- domain(Y, [nothing, just(_)]).

maybe_map(F,MaybeY,D) :- 
    is_maybe(MaybeY), 
    (
        MaybeY = nothing, 
        D = nothing
    ; 
        MaybeY = just(Y), 
        call(F,Y,X), 
        D = just(X)
    ) .

maybe_map(F,MaybeY,D) :- 
    \+ is_maybe(MaybeY), type_error(maybe,MaybeY).

```

Then use it all:

```prolog
inc(X,Y) :- #(Y) #= #(X) + 1.

?- domain(X, [M, pizza]), maybe_map(inc, X ,Y).
X = Y, Y = nothing ;
X = just(_A),
Y = just(_B),
clpfd: #=(_A+1, _B) ;

```

Now I haven’t _actually_ used this yet in my real code. But at first glance it looks like what I _think_ I want for my peace of mind.  
Any objections or suggestions?

---

<div class="post-metadata">

**Author:** ![RdR](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/rdr/32/379_2.png) [@RdR](https://swi-prolog.discourse.group/u/RdR)\
**Post date:** [June 28, 2023, 8:58pm UTC](https://swi-prolog.discourse.group/t/in-lieu-of-a-type-system/6666/2 "2023-06-28T20:58:58Z")

</div>

Small, simple – good in that regard. But imho, already elaborate enough that I would probably choose something like the mavis addon instead.

I really love the way mavis is integrated with the comment predicate declarations.
