我试图设计嵌入式语言,其中的操作可以提高某些标志取决于值。我预见了对标量值和向量的操作(例如地图,折叠等)。我的想法是使用Writer Monad来跟踪标志。简单的例子,在实际类型为“内部”,如果任何参数的值为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))
我有点不确定什么是实现这一目标的最佳途径旗升起。有些问题:
我应该定义所有的操作,比如我做了
bplus
或像wbplus
。看起来,Laters使组合更容易。但要使用foldM
二元运算符应具有类型Int -> Int -> WInt
。什么是列表的适当类型:
Writer Any [Int]
或[Wint]
?
任何建议或想法的赞赏。
我认为这是有点不清楚你在问什么。 “我很少不确定什么是最好的实施方式。” - 目前的实施有什么问题?如果你解释你当前实现的哪些部分不令人满意,那么这个问题变得更加清晰。如果解决方案是完全令人满意的,那么我无法想象会有什么问题... – user2407038
我已经澄清了我的一些问题。 – krokodil
我会使用'wbplus'公式 - 它自然适合更好,因为'+'在道德上是一个二元运算符。你不需要使用'foldM' - 'foldr wbplus :: WInt - > [WInt] - > WInt'。你可能会将列表表示为'[WInt]',因为你可以将其转换为'Writer Any [Int]'而不是其他方式('sequence :: [Writer Any Int] - > Writer Any [Int ]') – user2407038