我正在尝试设计嵌入式语言,其中操作可以根据值引发某些标志。我预见到对标量值以及向量(例如映射、折叠等)的操作。我的想法是使用 Writer Monad 来跟踪标志。简化示例,其中实际类型为“Int”,如果任何参数为 0,则引发标志。
import Control.Monad.Identity
import Control.Monad.Writer
import Data.Monoid
type WInt = Writer Any Int
bplus :: Int -> Int -> WInt
bplus a b =
do
tell (Any (a == 0 || b == 0)) ;
return (a+b)
wbplus :: WInt -> WInt -> WInt
wbplus wa wb =
do
a <- wa ;
b <- wb ;
tell (Any (a == 0 || b == 0)) ;
return (a+b)
ex0 = runWriter (bplus 1 2)
ex1 = runWriter (bplus 0 2)
ex2 = runWriter (wbplus (return 1) (return 2))
ex3 = runWriter (wbplus (return 0) (return 2))
ex4 = runWriter (wbplus (wbplus (return 1) (return 2)) (return 2))
ex5 = runWriter (wbplus (wbplus (return 0) (return 2)) (return 2))
ex6 = runWriter (wbplus (wbplus (return 1) (return 2)) (return 0))
我不太确定实现这一点的最佳方法是什么。一些问题:
我应该像 for 一样定义所有操作
bplus
吗wbplus
?看起来,Latters 让作曲变得更容易了。但是要使用foldM
二元运算符应该有类型Int -> Int -> WInt
。列表的合适类型是什么:
Writer Any [Int]
或[Wint]
?
任何建议或想法表示赞赏。