Как обновить части штата в государственной монаде?

Однако есть небольшая лазейка: если вы определите свой Foo класс как абстрактный. Это означало бы, что вам нужно создать экземпляр класса следующим образом:

Foo<MyType> myFoo = new Foo<MyType>(){};

(Обратите внимание на двойные фигурные скобки в конце.)

Теперь вы можете получить тип T во время выполнения :

Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];

Обратите внимание, что mySuperclass должен быть суперклассом определения класса, фактически определяющим конечный тип для T.

Он также не очень изящный, но вы должны решить, предпочитаете ли вы new Foo<MyType>(){} или new Foo<MyType>(MyType.class); в своем коде.


Например:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.NoSuchElementException;

/**
 * Captures and silently ignores stack exceptions upon popping.
 */
public abstract class SilentStack<E> extends ArrayDeque<E> {
  public E pop() {
    try {
      return super.pop();
    }
    catch( NoSuchElementException nsee ) {
      return create();
    }
  }

  public E create() {
    try {
      Type sooper = getClass().getGenericSuperclass();
      Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];

      return (E)(Class.forName( t.toString() ).newInstance());
    }
    catch( Exception e ) {
      return null;
    }
  }
}

Затем:

public class Main {
    // Note the braces...
    private Deque<String> stack = new SilentStack<String>(){};

    public static void main( String args[] ) {
      // Returns a new instance of String.
      String s = stack.pop();
      System.out.printf( "s = '%s'\n", s );
    }
}
1
задан melpomene 14 July 2018 в 01:06
поделиться

1 ответ

Я считаю, что вы можете сделать это с помощью комбинатора zoom из Control.Lens.Zoom:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad.State
data SomeState = SomeState { _int :: Int, _string :: String } deriving (Show)
makeLenses ''SomeState
updateInt :: Int -> State Int ()
updateInt x = id .= x
updateString :: String -> State String ()
updateString x = id .= x

updateSomeState :: Int -> State SomeState ()
updateSomeState x = zoom int (updateInt x)

GHCi:

*Main> runStateT (updateSomeState 5) (SomeState 3 "hi")
 Identity ((),SomeState {_int = 5, _string = "hi"})
1
ответ дан Peter Amidon 17 August 2018 в 12:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: