SYB 초보자이기 때문에 내 대답은 추측과 비슷하지만 작동하는 것처럼 보입니다.
결합 자 somewhere
닐 브라운 (Neil Brown)이 권장하는 것은 아마도 사용자가 원하는대로 할 수 없습니다. 우리가 에서 가장 번을 변환 할 필요가 defined 그러나
-- | Apply a monadic transformation at least somewhere
somewhere :: MonadPlus m => GenericM m -> GenericM m
-- We try "f" in top-down manner, but descent into "x" when we fail
-- at the root of the term. The transformation fails if "f" fails
-- everywhere, say succeeds nowhere.
--
somewhere f x = f x `mplus` gmapMp (somewhere f) x
-- | Transformation of at least one immediate subterm does not fail
gmapMp :: forall m. MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a
그것은이다. 이를 위해이
gmapMo
이 더 좋을 것으로 보인다 :
-- | Transformation of one immediate subterm with success
gmapMo :: forall m. MonadPlus m => (forall d. Data d => d -> m d) -> a -> m a
그래서 난 내 자신의 콤비했다 : 대체가 실패
{-# LANGUAGE DeriveDataTypeable, RankNTypes #-}
import Control.Monad
import Data.Maybe (fromMaybe)
import Data.Data
import Data.Typeable (Typeable)
import Data.Generics.Schemes
import Data.Generics.Aliases
-- | Apply a monadic transformation once.
once :: MonadPlus m => GenericM m -> GenericM m
once f x = f x `mplus` gmapMo (once f) x
경우가 mzero
을 반환합니다, 그렇지 않으면 대체 된 결과를 반환합니다. 대체이 (더 일치)가 실패하지 않는 경우 당신은 상관하지 않는 경우, 당신은 우리가 일부 교체 할 수있는 이들과 함께
once' :: (forall a. Data a => a -> Maybe a) -> (forall a. Data a => a -> a)
once' f x = fromMaybe x (once f x)
같은 것을 사용할 수 있습니다
data Exp = Var String | Val Int | Plus Exp Exp
deriving (Show, Typeable, Data)
myExp = Val 5 `Plus` Var "x" `Plus` Val 5 `Plus` Var "x"
replM :: (MonadPlus m) => Exp -> m Exp
replM (Var "x") = return $ Var "y"
replM t = mzero
main = do
-- `somewhere` doesn't do what we want:
print $ (somewhere (mkMp replM) myExp :: Maybe Exp)
-- returns `Just ..` if the substitution succeeds once,
-- Nothing otherwise.
print $ (once (mkMp replM) myExp :: Maybe Exp)
-- performs the substitution once, if possible.
print $ (once' (mkMp replM) myExp :: Exp)
-- Just for kicks, this returns all possible substitutions
-- where one `Var "x"` is replaced by `Var "y"`.
print $ (once (mkMp replM) myExp :: [Exp])
우수한 솔루션! 정확히 내가 무엇을 찾고 있었는지. 대단히 감사합니다! – user1546806
내 코드에서이 작업을 수행하려면'once f x = f x \'mplus \'gmapMo (once f) x'로 다시 작성해야했습니다. – user1546806
@ user1546806 예, 죄송합니다. 그건 바보 같은 실수였습니다. 나는 답을 바로 잡을 것이다. –