-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDomainSetsCore.jl
111 lines (81 loc) · 2.42 KB
/
DomainSetsCore.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
module DomainSetsCore
export Domain,
domain,
domaineltype,
DomainStyle,
IsDomain,
NotDomain,
DomainRef,
AnyDomain,
checkdomain
"""
domaineltype(d)
The `domaineltype` of a continuous set is a valid type for elements of that set.
By default it is equal to the `eltype` of `d`, which in turn defaults to `Any`.
"""
domaineltype(d) = eltype(d)
"""
A `Domain{T}` is a supertype for domains with `domaineltype` equal to `T`.
In addition, the `eltype` of a `Domain{T}` is also equal to `T`.
"""
abstract type Domain{T} end
domaineltype(d::Domain{T}) where T = T
"""
DomainStyle(d)
Trait to indicate whether or not `d` implements the domain interface.
"""
abstract type DomainStyle end
"""
IsDomain()
indicates an object implements the domain interface.
"""
struct IsDomain <: DomainStyle end
"""
NotDomain()
indicates an object does not implement the domain interface.
"""
struct NotDomain <: DomainStyle end
DomainStyle(d) = DomainStyle(typeof(d))
# - the default is no domain
DomainStyle(::Type) = NotDomain()
# - subtypes of Domain are domains
DomainStyle(::Type{<:Domain}) = IsDomain()
# - declare Number, AbstractSet and AbstractArray to be valid domain types
DomainStyle(::Type{<:Number}) = IsDomain()
DomainStyle(::Type{<:AbstractSet}) = IsDomain()
DomainStyle(::Type{<:AbstractArray}) = IsDomain()
"""
domain(d)
Return a domain associated with the object `d`.
"""
domain(d::Domain) = d
"""
DomainRef(d)
A reference to a domain.
In a function call, `DomainRef(x)` can be used to indicate that `x` should be
treated as a domain, e.g., `foo(x, DomainRef(d))`.
"""
struct DomainRef{D}
domain :: D
end
domain(d::DomainRef) = d.domain
domaineltype(d::DomainRef) = domaineltype(domain(d))
"""
`AnyDomain` is the union of `Domain` and `DomainRef`.
In both cases `domain(d::AnyDomain)` returns the domain itself.
"""
const AnyDomain = Union{Domain,DomainRef}
"""
checkdomain(d)
Checks that `d` is a domain or refers to a domain and if so returns that domain,
throws an error otherwise.
"""
checkdomain(d::Domain) = d
# we trust the explicit intention of a user providing a domain reference
checkdomain(d::DomainRef) = domain(d)
# for other objects we check DomainStyle
checkdomain(d) = _checkdomain(d, DomainStyle(d))
_checkdomain(d, ::IsDomain) = d
_checkdomain(d, ::NotDomain) =
error("Domain does not implement domain interface as indicated by DomainStyle.")
end # module DomainSetsCore