无积分转换
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
.
更合适
我有一些 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
.