Monads/Maybe monad: Difference between revisions

Line 1,217:
 
=={{header|M2000 Interpreter}}==
Revision 1. Now the operator "=" check if we have same status on haveValue for the two objects. If not we get the false in compare. Also the unit() function return "none" object from a an object not "none".
 
M2000 create objects (of type Group) either from a Class (which is a function), or from a copy of an object. The life of an object depends of the storing site, and the use of a pointer or not. Here all objects are one of two kinds: Objects like none, m1, m2, m3 and m5 are destruct at the exit of the module. Object on the SetA like none and none.unit() (which is a copy of none), destruct when last pointer (here SetA) deleted, and for this example, because SetA is local variable, the delete happen at the exit of current module. The m object which used in Bind() and Unit() function, and the g object are all objects which life end at the exit of those function, although these functions return a pointer to a copy of the m object, and check an internal field which make it "float". A float object is something different from an object holding by a pointer. M2000 always "expand" a float object when we place it to a variable (as a copy, or if the variable hold another object - always as group else we get error 0 - as a merge of these). So when we pick a "float" object from array, we get a copy. M2000 can use pointer to groups. The second list show how we can use pointers to groups. Pointers can be one of two types: A real pointes (here we use real pointers), or a weak pointer. The -> operator in a ->m (or =pointer(m)) where m hold a group (not a pointer) return a weak pointer (invalid if actual variable not exist). Here we use ->(m) which make m a float group and then change it to a pointer to float group (same as =pointer((m))). A pointer(none) return a real pointer if none is a pointer to group, or a weak pointer if it isn't a pointer. A pointer to group is a group, not an address. A pointer() return the Null pointer (which is a group of type Null). The Null group (user object in M2000), has a type that cannot inherit to other classes, also in a group merge with null we don't merge Null type. Merging is another way to produce groups from two or more other types, using objects (not classes).
 
===== Without using pointers =====
 
<syntaxhighlight lang="m2000 interpreter">
Line 1,233 ⟶ 1,238:
}
Operator "=" (z as maybe) {
if z.havevalue xor .havevalue then
Push z.[val]=.[val]
push false
else
Push z.[val]=.[val]
end if
}
Function unit() {
Line 1,247 ⟶ 1,256:
m.[val]=v
m.haveValue=true
else // so now we can produce "none" from an object which isn't "none"
m.[val]="none"
m.haveValue=false
end if
=m // copy (not pointer)
}
class:
// after class: all are temporary for the constructionconstuction phase
// module with class name is the constructorcontructor
// the object constructedconstracted before enter this module
// but we can change it. So we return a new one.
module maybe {
Line 1,272 ⟶ 1,284:
k=each(SetA)
While K
m1=none.unit(array(Kk)) // pick element k^
m2=m1.bind(decrement).bind(triple)
m3=maybe(m2)
Line 1,281 ⟶ 1,293:
}
Print not ok // true , "Hello" not accepted
</syntaxhighlight>
 
 
===== Using pointers =====
 
 
<syntaxhighlight lang="m2000 interpreter">
Class maybe {
private:
variant [val]="none"
boolean haveValue
public:
property val {
value // val return the [val] value
}
function bind(f) {
m=This // we can read private because bind is function of same class as m
if m.haveValue Then m.[val]=f(m.[val])
->(m) // pointer
}
Operator "=" (z as maybe) {
if z.havevalue xor .havevalue then
push false
else
Push z.[val]=.[val]
end if
}
Function unit() {
variant k
if match("G") then // so we can read maybe class
read g as maybe // fail if not maybe class
if g.havevalue then push g.val
end if
Read ? k
m=This
if not type$(k)="Empty" then
integer v=k ' fail if k can't convert to integer
m.[val]=v
m.haveValue=true
else // so now we can produce "none" from an object which isn't "none"
m.[val]="none"
m.haveValue=false
end if
->(m) // pointer
}
class:
module maybe {
if not empty then
this=.unit(![])
end if
}
}
none->maybe()
decrement =lambda (x as integer)->x-1%
triple =lambda (x as integer)->x*3%
variant emptyvariant
SetA=(3,4,none,5%, emptyvariant, none=>unit())
k=each(SetA)
document doc$
While k
m1=none=>unit(array(k)) // pick element k^
m2=m1=>bind(decrement)=>bind(triple)
m3=maybe(m2)
doc$=m1=>val+" -> "+m2=>val+" m2=m3 -> "+if$(m2=m3->"True", "False")+{
}
End While
Try ok {
m5=maybe("Hello")
}
Doc$= (not ok)+{
} // true , "Hello" not accepted
report doc$
clipboard doc$
</syntaxhighlight>
{{out}}
404

edits