无积分转换

Pointfree conversion

我有一些 traverse/accessor 函数可用于我的网格类型:

cell :: Mesh a -> Int -> Maybe (Cell a)
neighbour :: Mesh a -> Int -> Cell a -> Maybe (Cell a)
owner :: Mesh a -> Cell a -> Maybe (Cell a)

为了避免将网格传递给每个函数并处理失败,我通过这个复合 monad 创建了它们的 monadic 版本:

type MMesh a b = MaybeT (State (Mesh a)) b

所以,我有这样的 monadic 访问器:

getMesh = get :: MMesh a (Mesh a) -- just to remove type declarations

cellM id = getMesh >>= (MaybeT . return) <$> (\m -> cell m id)
neighbourM idx cell = getMesh >>= (MaybeT . return) <$> (\m -> neighbour m idx cell)
ownerM cell = getMesh >>= (MaybeT . return) <$> (\m -> owner m cell)

它们显然遵循相同的模式,我很乐意将公共部分移动到某个外部函数,比如 liftMesh 将上面的代码重写为:

cellM = liftMesh cell
neighbourM = liftMesh neighbour
ownerM - liftMesh owner

但这首先需要以 pointfree 风格重写函数以省略可变数量的参数。这就是我卡住的地方,所以任何人都可以帮助将其转换为 pointfree 或找到其他方法来获得相同的结果吗?

更新:在此处添加全文:http://pastebin.com/nmJVNx93

只需使用gets,其中returns由任意函数指定的状态在其上的投影,以及MaybeT:

cellM ix = MaybeT (gets (\m -> cell m ix))

neighbourM ix c = MaybeT (gets (\m -> neighbour m ix c))

owner c = MaybeT (gets (\m -> owner m c))

(N.B.: 我建议不要命名东西 id。标准的 id 功能太重要了,名字冲突很混乱。)

为了使这更有意义,请根据需要重新排序函数的参数。例如:

cell :: Int -> Mesh a -> Maybe (Cell a)

cellM ix = MaybeT (gets (cell ix))

(您可以一直写成 cellM = MaybeT . gets . cell,但我觉得那样会过度模糊 cellM 的作用。)

P.S.: 鉴于您正在使用 State,很可能您也对修改网格的函数感兴趣。但是,如果您不是,Reader 会比 State.

更合适