Suma de hlist (donde todos los elementos son los nativos) -- scala camp codereview Relacionados El problema

Sum of HList (where all elements are Nat's)


2
vote

problema

Español

Escribí lo siguiente a la salida, a nivel de tipo, la suma, class Area { public: Area(){} ~Area(){} private: string m_Id; }; class IData { private: OGRLayer * m_Layer; public: ~IData() {} IData(OGRLayer *layer) { m_Layer = layer; } OGRLayer* getLayer(); }; OGRLayer* IData::getLayer() { return m_Layer; } class Areas { public: Areas(){} Areas(std::shared_ptr<IData> data); vector<Area> getAreas(); ~Areas(){} private: std::shared_ptr<IData> m_Data; vector<Area> m_Areas; }; Areas::Areas(std::shared_ptr<IData> data) { m_Data = data; } vector<Area> Areas::getAreas() { if(m_Data == nullptr) return vector<Area>(); // Declare variable for reading the features from a WFS layer OGRFeature *Feature; // Reset Reading (Although not necessary now because it hasnt been read yet, this is good practice before reading WFS data) m_Data->getLayer()->ResetReading(); while ((Feature = m_Data->getLayer()->GetNextFeature()) != NULL) { // Variable initialised to contain the definitions of all of the fileds in the WFS Layer OGRFeatureDefn *FeatureDefinition = m_Data->getLayer()->GetLayerDefn(); for (int i = 0; i < FeatureDefinition->GetFieldCount(); i++) { // Variable initialised to contain field data at the current index of i OGRFieldDefn *FieldDefinition = FeatureDefinition->GetFieldDefn(i); if (FieldDefinition->GetType() == OFTInteger) { std::cout << Feature->GetFieldAsInteger(i) << ","; } else if (FieldDefinition->GetType() == OFTReal) { std::cout << Feature->GetFieldAsDouble(i) << ","; } else if (FieldDefinition->GetType() == OFTString) { std::cout << Feature->GetFieldAsString(i) << ","; } else { std::cout << Feature->GetFieldAsString(i) << ","; } } // Variable initialised to contain Geometry point data for the field at the current index of i OGRGeometry *Geometry = Feature->GetGeometryRef(); if (Geometry != NULL && wkbFlatten(Geometry->getGeometryType()) == wkbPoint) { OGRPoint *Point = (OGRPoint *)Geometry; // Maybe need to limit the number of decimal places for X and Y coordinates to 2-3 std::cout << Point->getX() << "," << Point->getY() << std::endl; } else { std::cout << "No Point Geometry" << std::endl; } OGRFeature::DestroyFeature(Feature); } } struct IConnection { virtual std::shared_ptr<IData> QueryLayer(string layer) = 0; virtual int Write(IData *data) = 0; virtual void Release() = 0; IConnection() {} virtual ~IConnection() {} }; struct ImplIConnection : public IConnection { OGRDataSource *m_wfs_t; public: ImplIConnection(OGRDataSource *dataset) { m_wfs_t = dataset; } ~ImplIConnection() {} private: std::shared_ptr<IData> QueryLayer(string data); int Write(IData *data); void Release(); }; std::shared_ptr<IData> ImplIConnection::QueryLayer(string layerName) { OGRLayer *Layer = m_wfs_t->GetLayerByName(layerName.c_str()); if (Layer == NULL) { return NULL; } std::shared_ptr<IData> data(new IData(Layer)); return data; } int ImplIConnection::Write(IData *data) { return 0; } void ImplIConnection::Release() { } struct IMapServer { virtual std::shared_ptr<IConnection> OpenConnection(string url) = 0; virtual void Release() = 0; IMapServer() {} virtual ~IMapServer() {} }; struct ImplMapServer : public IMapServer { private: OGRDataSource *m_wfs_t; public: ImplMapServer() {} ~ImplMapServer() { OGRDataSource::DestroyDataSource(m_wfs_t); } void Init(void); std::shared_ptr<IConnection> OpenConnection(string url); void Release() {}; }; std::shared_ptr<IConnection> ImplMapServer::OpenConnection(string url) { m_wfs_t = OGRSFDriverRegistrar::Open(url.c_str(), true); if (m_wfs_t == NULL) { return NULL; } std::shared_ptr<ImplIConnection> connection(new ImplIConnection(m_wfs_t)); return connection; } void ImplMapServer::Init(void) { CPLSetConfigOption("CPL_DEBUG", "ON"); GDALAllRegister(); OGRRegisterAll(); } 8 , de una entrada class Area { public: Area(){} ~Area(){} private: string m_Id; }; class IData { private: OGRLayer * m_Layer; public: ~IData() {} IData(OGRLayer *layer) { m_Layer = layer; } OGRLayer* getLayer(); }; OGRLayer* IData::getLayer() { return m_Layer; } class Areas { public: Areas(){} Areas(std::shared_ptr<IData> data); vector<Area> getAreas(); ~Areas(){} private: std::shared_ptr<IData> m_Data; vector<Area> m_Areas; }; Areas::Areas(std::shared_ptr<IData> data) { m_Data = data; } vector<Area> Areas::getAreas() { if(m_Data == nullptr) return vector<Area>(); // Declare variable for reading the features from a WFS layer OGRFeature *Feature; // Reset Reading (Although not necessary now because it hasnt been read yet, this is good practice before reading WFS data) m_Data->getLayer()->ResetReading(); while ((Feature = m_Data->getLayer()->GetNextFeature()) != NULL) { // Variable initialised to contain the definitions of all of the fileds in the WFS Layer OGRFeatureDefn *FeatureDefinition = m_Data->getLayer()->GetLayerDefn(); for (int i = 0; i < FeatureDefinition->GetFieldCount(); i++) { // Variable initialised to contain field data at the current index of i OGRFieldDefn *FieldDefinition = FeatureDefinition->GetFieldDefn(i); if (FieldDefinition->GetType() == OFTInteger) { std::cout << Feature->GetFieldAsInteger(i) << ","; } else if (FieldDefinition->GetType() == OFTReal) { std::cout << Feature->GetFieldAsDouble(i) << ","; } else if (FieldDefinition->GetType() == OFTString) { std::cout << Feature->GetFieldAsString(i) << ","; } else { std::cout << Feature->GetFieldAsString(i) << ","; } } // Variable initialised to contain Geometry point data for the field at the current index of i OGRGeometry *Geometry = Feature->GetGeometryRef(); if (Geometry != NULL && wkbFlatten(Geometry->getGeometryType()) == wkbPoint) { OGRPoint *Point = (OGRPoint *)Geometry; // Maybe need to limit the number of decimal places for X and Y coordinates to 2-3 std::cout << Point->getX() << "," << Point->getY() << std::endl; } else { std::cout << "No Point Geometry" << std::endl; } OGRFeature::DestroyFeature(Feature); } } struct IConnection { virtual std::shared_ptr<IData> QueryLayer(string layer) = 0; virtual int Write(IData *data) = 0; virtual void Release() = 0; IConnection() {} virtual ~IConnection() {} }; struct ImplIConnection : public IConnection { OGRDataSource *m_wfs_t; public: ImplIConnection(OGRDataSource *dataset) { m_wfs_t = dataset; } ~ImplIConnection() {} private: std::shared_ptr<IData> QueryLayer(string data); int Write(IData *data); void Release(); }; std::shared_ptr<IData> ImplIConnection::QueryLayer(string layerName) { OGRLayer *Layer = m_wfs_t->GetLayerByName(layerName.c_str()); if (Layer == NULL) { return NULL; } std::shared_ptr<IData> data(new IData(Layer)); return data; } int ImplIConnection::Write(IData *data) { return 0; } void ImplIConnection::Release() { } struct IMapServer { virtual std::shared_ptr<IConnection> OpenConnection(string url) = 0; virtual void Release() = 0; IMapServer() {} virtual ~IMapServer() {} }; struct ImplMapServer : public IMapServer { private: OGRDataSource *m_wfs_t; public: ImplMapServer() {} ~ImplMapServer() { OGRDataSource::DestroyDataSource(m_wfs_t); } void Init(void); std::shared_ptr<IConnection> OpenConnection(string url); void Release() {}; }; std::shared_ptr<IConnection> ImplMapServer::OpenConnection(string url) { m_wfs_t = OGRSFDriverRegistrar::Open(url.c_str(), true); if (m_wfs_t == NULL) { return NULL; } std::shared_ptr<ImplIConnection> connection(new ImplIConnection(m_wfs_t)); return connection; } void ImplMapServer::Init(void) { CPLSetConfigOption("CPL_DEBUG", "ON"); GDALAllRegister(); OGRRegisterAll(); } 9 :

  std::shared_ptr<IConnection> connection = mapserver.OpenConnection("WFS:http://192.168.139.129/cgi-bin/tinyows.exe");     std::shared_ptr<IData> frida = connection->QueryLayer("frida");     Areas *areas = new Areas(frida);      vector<Area> areasVector = areas->getAreas(); 0  

Pruebas:

  std::shared_ptr<IConnection> connection = mapserver.OpenConnection("WFS:http://192.168.139.129/cgi-bin/tinyows.exe");     std::shared_ptr<IData> frida = connection->QueryLayer("frida");     Areas *areas = new Areas(frida);      vector<Area> areasVector = areas->getAreas(); 1  

por favor crítico mi código. Además, ¿estoy usando la inducción para determinar la suma para el caso no HNIL?

Original en ingles

I wrote the following to output, at the type level, the sum, Nat, of an input HList:

trait HListSum[L] {   type Out } object HListSum {    type Aux[L, O] = HListSum[L] { type Out = O }    def apply[L <: HList](implicit ev: HListSum[L]): ev.type = ev    implicit def hListSumInductive[H <: Nat, L <: HList, S <: Nat, T <: Nat](     implicit rest: HListSum.Aux[L, T],              all: Sum.Aux[H, T, S]): HListSum.Aux[H :: L, S] = new HListSum[H :: L] {     type Out = S   }    implicit val hlistSumHNil: HListSum.Aux[HNil, _0] = new HListSum[HNil] {     type Out = _0   } } 

Testing:

import net.HListSum import shapeless._ import nat._  scala> HListSum[_1 :: _2 :: _3 :: HNil] res0: net.HListSum.Aux[shapeless.::[shapeless.nat._1,shapeless.::[shapeless.nat._2,shapeless.::[shapeless.nat._3,shapeless.HNil]]],this.Out] = net.HListSum$$anon$4@132c4879  scala> val expected: res0.Out = _6 expected: res0.Out = Succ()  scala> HListSum[_0 :: _0 :: _1 :: HNil] res1: net.HListSum.Aux[shapeless.::[shapeless.nat._0,shapeless.::[shapeless.nat._0,shapeless.::[shapeless.nat._1,shapeless.HNil]]],this.Out] = net.HListSum$$anon$4@a7b83a8  scala> val expected2: res1.Out = _1 expected2: res1.Out = Succ()  scala> val expected2: res1.Out = _3 <console>:19: error: type mismatch;  found   : shapeless.nat._3     (which expands to)  shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]]  required: res1.Out     (which expands to)  shapeless.Succ[shapeless._0]        val expected2: res1.Out = _3                                  ^ 

Please critique my code. Also, am I using induction to determine the sum for the non-HNil case?

  

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

primero para algunas pequeñas cosas. Pondría límites en el parámetro de tipo L 99887776655544330 Tipo Miembro para capturar los hechos que conoce siempre será verdadero acerca de ellos:

  trait HListSum[L <: HList] {   type Out <: Nat }   

Esto hace que la intención sea más clara a los lectores y le permite usar Out en lugares que no podía, por lo que, por lo que, por ejemplo,. Este ejemplo simple no se compilaría sin el límite:

  scala> def foo[N <: Nat]: Unit = () foo: [N <: shapeless.Nat]=> Unit  scala> def bar[L <: HList](implicit sum: HListSum[L]): Unit = foo[sum.Out] bar: [L <: shapeless.HList](implicit sum: HListSum[L])Unit   

También cambiaría el tipo de devolución de apply Para ser un poco más específico (o bastante menos específico, supongo, más enfocado en lo que es relevante, en cualquier caso):

  def apply[L <: HList](implicit ev: HListSum[L]): Aux[L, ev.Out] = ev   

Esto es principalmente para la legibilidad, aparte de la forma en que se imprime el tipo en la consola, no estoy seguro de la parte superior de mi cabeza, ya sea que haya una diferencia real entre esta y la versión 99887776655544337 . < / p>

Haría dos cambios en la implementación hListSumInductive (aparte de cambiar el caso del l en el nombre para ser consistente con Out0 ):

  Out1  

La primera es que he cambiado de nombre Out2 y 9988776655443114314 , desde que usando < CÓDIGO> Out6 y Out7 Para nombrar los tipos de cabeza y cola de un hlist es una convención bastante estándar. Más significativamente, he dejado caer el parámetro de tipo hListSumInductive18 (que representa la suma total), ya que no necesitamos un parámetro de tipo para referirse a ese tipo ( 99887776655443319 funciona simplemente bien, ya que no necesitamos referirnos a él en otros parámetros implícitos).

Otra nota sobre este método: No estoy seguro de si eligió trait HListSum[L <: HList] { type Out <: Nat } 0 sobre trait HListSum[L <: HList] { type Out <: Nat } 1 intencionalmente, pero es lo correcto si le importa los tiempos de compilación (Y debería en un caso de esta), ya que la instancia se resolverá más rápidamente cuando el número más grande está a la derecha, y en esta operación, el número más grande será trait HListSum[L <: HList] { type Out <: Nat } 2 más a menudo.

Otra cosa pequeña, probablemente renombraría trait HListSum[L <: HList] { type Out <: Nat } 3 en trait HListSum[L <: HList] { type Out <: Nat } 4 :

  trait HListSum[L <: HList] {   type Out <: Nat } 5  

sobre todo porque trait HListSum[L <: HList] { type Out <: Nat } 6 es fácil de confundir con trait HListSum[L <: HList] { type Out <: Nat } 7 , y porque personalmente tiendo a usar el sufijo 998877766655443328 como una convención en estos casos . Sin embargo, eso es por completo una cuestión de gusto.

Por último, si estuviera escribiendo esto para una biblioteca, probablemente usaría una clase abstracta sellada en lugar de Un rasgo y lo haría Hacer el objeto Final , pero ni el cambio es terriblemente importante.

 

First for some little things. I'd put bounds on the L type parameter and the Out type member to capture the facts that you know will always be true about them:

trait HListSum[L <: HList] {   type Out <: Nat } 

This makes the intent clearer to readers and allows you to use Out in places you couldn't otherwisexe2x80x94e.g. this simple example wouldn't compile without the bound:

scala> def foo[N <: Nat]: Unit = () foo: [N <: shapeless.Nat]=> Unit  scala> def bar[L <: HList](implicit sum: HListSum[L]): Unit = foo[sum.Out] bar: [L <: shapeless.HList](implicit sum: HListSum[L])Unit 

I'd also change the return type of apply to be a little more specific (or rather less specific, I guessxe2x80x94more focused on what's relevant, in any case):

def apply[L <: HList](implicit ev: HListSum[L]): Aux[L, ev.Out] = ev 

This is mostly for legibilityxe2x80x94apart from how the type is printed in the console I'm not sure off the top of my head whether there's any real difference between this and the ev.type version.

I'd make two changes to the hListSumInductive implementation (apart from changing the case of the l in the name to be consistent with hlistSumHNil):

implicit def hlistSumInductive[H <: Nat, T <: HList, TS <: Nat](implicit   rest: HListSum.Aux[T, TS],   all: Sum[H, TS] ): HListSum.Aux[H :: T, all.Out] = new HListSum[H :: T] {   type Out = all.Out } 

The first is that I've renamed L to T and T to TS, since using H and T to name the head and tail types of an hlist is a pretty standard convention. More significantly, I've dropped the S type parameter (representing the total sum) altogether, since we don't need a type parameter to refer to that type (all.Out works just fine, since we don't need to refer to it in other implicit parameters).

One other note about this method: I'm not sure whether you chose Sum[H, TS] over Sum[TS, H] intentionally, but it's the right thing to do if you care about compile times (and you should in a case like this), since the instance will be resolved more quickly when the larger number is on the right, and in this operation the larger number will be TS more often.

One other tiny thingxe2x80x94I'd probably rename O in Aux:

type Aux[L <: HList, Out0] = HListSum[L] { type Out = Out0 } 

Mostly because O is easy to confuse with 0, and because I personally tend to use the 0 suffix as a convention in these cases. That's entirely a matter of taste, though.

Lastly, if I were writing this for a library I'd probably use a sealed abstract class instead of a trait and would make the object final, but neither change is terribly important.

 
 
   
   

Relacionados problema

4  "Funcionalizando" este método de caminar de árbol y limpiándolo  ( Functionalizing this tree walking method and cleaning it up ) 
Tengo una clase 99887776655443316 que representa un árbol binario de negativo / positivo. Estoy buscando mejorar mi método OdbcConnection7 y hazlo más fun...

11  Escáner en Scala  ( Scanner in scala ) 
que quería implementar 'código> 99887766555443333 / Código> en Scala. El objetivo de esta clase es: implementar una interfaz de colección SCALA (probable...

3  Definiendo la transposición en una colección de colecciones irregulares  ( Defining transpose on a collection of irregular collections ) 
Me pidieron que presentara mi solicitud de revisión de código en https: //stackoverflow.com/questions/10672046/defining-transpose-on-a-collection-of-irregula...

2  Un generador de laberinto Scala en estilo funcional  ( A scala maze generator in functional style ) 
Me pregunto si hay más que puedo hacer para incorporar más principios de programación de Scala y funcionales idiomáticos. Sé que el laberinto es silencioso, p...

6  Secuencia de fecha de construcción en Scala  ( Construct date sequence in scala ) 
Quiero tener una secuencia de fecha continua como ['2014-01-01', '2014-01-02', ...] Entonces defino un arroyo para hacer eso. def daySeq(start: Date): St...

2  Scala Mastermind Solver, que es la más scala-ish  ( Scala mastermind solver which is the most scala ish ) 
Estoy tratando de expresar el Kata TDD clásico de Mastermind en la Scala Idiomática que puedo. Aquí hay una suite de prueba escalada: buf1 y mi implemen...

6  Una implementación de Scala del método de ajuste Java  ( A scala implementation of the java trim method ) 
Soy un principiante de Scala y mirando el método $_{456}$3655443323 de la API de Java. Noté los efectos secundarios, así que intenté implementar una versión...

3  Árbol de búsqueda binaria de Scala  ( Scala binary search tree ) 
En un intento de profundizar en Scala, decidí hacer un BST usando tantos conceptos interesantes como sea posible para explorar todo lo que Scala tiene para of...

6  Implementación de índice de equilibrio  ( Equilibrium index implementation ) 
He encontrado una solución a la problema de índice de equilibrio con la ayuda de las respuestas fuera aquí : val in = Stream(-7, 1, 5, 2, -4, 3, 0) val ...

8  Generación de mazmorras en Scala  ( Dungeon generation in scala ) 
Recientemente he comenzado a aprender Scala, y mientras me he encontrado con sus conceptos antes (inmutabilidad, tuplas, funciones de primera clase) No estoy ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos