Implementación de la mónada de estado y la notación “do” de Haskell en Wolfram
Implementación de la mónada de estado y la notación “do” de Haskell en Wolfram
por Eric Parfitt
Este cuaderno es una traducción al español del artículo de la Comunidad Wolfram “Implementing Haskell's state monad and do notation in Wolfram” producido con ayuda de un LLM y verificado por un traductor profesional
Introducción
Introducción
Recientemente he estado aprendiendo Haskell y decidí ver si podía implementar mónadas en Wolfram Language. Para probar esto, también he implementado una versión de la notación “do” de Haskell y la mónada de “estado”.
Problemas
Problemas
Un problema con el que me encontré es que Wolfram Language hace lo siguiente:
Function
In[]:=
foo[f_]:=x|->f[x]
In[]:=
Nest[foo,b,3]
Out[]=
Function[x$,Function[x$,Function[x$,b[x$]][x$]][x$]]
Lo cual terminó causando problemas para mi función cuando las personas usaron la sintaxis “” para definir funciones en sus mónadas. Se puede evitar esto definiendo foo de manera equivalente como
In[]:=
foo[f_]:=f[#]&
In[]:=
Nest[foo,b,3]
Out[]=
((b[#1]&)[#1]&)[#1]&
(la respuesta que quería) pero quiero que el usuario de las mónadas no tenga que preocuparse por qué sintaxis específica utilizar para definir funciones, y que podría obtener la respuesta equivocada si utiliza la sintaxis “incorrecta”. Así que Kurt Gimbel me ayudó con esa parte, y realizó casi todo el diseño de la función “uniquizeVars”, la cual asegura que las funciones anidadas siempre tengan variables únicas cuando se supone que deben serlo. Si uno evita usar la sintaxis “” o Function con variables nombradas, puede simplemente prescindir de esa función, y la definición de las mónadas sería un poco más elegante. Pero yo quería esa característica, así que aquí está.
A continuación, defino el código para la notación “do” y la mónada “state”, y luego configuro y ejecuto algunos cálculos compuestos con estado que implican operaciones de push y pop, utilizando la notación “do” definida.
A continuación, defino el código para la notación “do” y la mónada “state”, y luego configuro y ejecuto algunos cálculos compuestos con estado que implican operaciones de push y pop, utilizando la notación “do” definida.
Código de notación “Do”
Código de notación “Do”
In[]:=
then[x_,y_]:=bind[x,y&]
In[]:=
myValueQ[expr_]:=ValueQ[expr,Method->"SymbolDefinitionsPresent"]||Context[expr]==="System`"
In[]:=
uniqueizeVars[expr_]:=Module[{},expr/.(Symbol[#]:>With[{eval=Symbol[#<>ToString[$ModuleNumber]]},eval/;True]&/@Cases[expr,sym_Symbol?(Not@*myValueQ):>SymbolName@Unevaluated[sym],{0,Infinity}])]
In[]:=
mDoPart[get[x_,y_],z_]:=bind[y,x|->z]
In[]:=
mDoPart[x_,y_]:=then[x,y]
In[]:=
mDo[x__]:=Fold[uniqueizeVars@mDoPart[#2,#1]&,Reverse[{x}]]
Código de la mónada de estado
Código de la mónada de estado
In[]:=
bind[state[h_],f_]:=state[s|->Replace[h[s],{a_,newState_}:>Replace[f[a],state[x_]:>x[newState]]]]
In[]:=
return[x_]:=state[{x,#}&]
In[]:=
runState[state[computation_],myState_List]:=computation[myState]
Definiciones push y pop
Definiciones push y pop
In[]:=
pushI[x_][{xs___}]:={{},{x,xs}}
In[]:=
push=state@*pushI;
In[]:=
popI[{x_,xs___}]:={x,{xs}}
In[]:=
pop=state[popI];
Configuración de manipulación de pila
Configuración de manipulación de pila
In[]:=
stackManip=mDo[push[3],pop,pop];
In[]:=
stackStuff=mDo[get[a,pop],If[a==5,push[5],mDo[push[3],push[8]]]];
In[]:=
moreStack=mDo[get[a,stackManip],If[a==100,stackStuff,return[{}]]];
Cálculos
Cálculos
In[]:=
runState[moreStack,{100,0,2,1,0}]
Out[]=
{{},{8,3,2,1,0}}
In[]:=
runState[moreStack,{100,5,2,1,0}]
Out[]=
{{},{5,2,1,0}}
In[]:=
runState[moreStack,{5,0,2,1,0}]
Out[]=
{{},{0,2,1,0}}
In[]:=
runState[moreStack,{5,5,2,1,0}]
Out[]=
{{},{5,2,1,0}}
CITE ESTE CUADERNO
CITE ESTE CUADERNO
Implementación de la mónada de estado y la notación “do” de Haskell en Wolfram
por Eric Parfitt
Comunidad Wolfram, STAFF PICKS, 13 de junio de 2025
https://community.wolfram.com/groups/-/m/t/3478726
por Eric Parfitt
Comunidad Wolfram, STAFF PICKS, 13 de junio de 2025
https://community.wolfram.com/groups/-/m/t/3478726