Últimamente he estado escribiendo código FFI que devuelve una estructura de datos en la mónada IO. Por ejemplo:Lo que se prefiere entre liftM, lilftA, etc.
peek p = Vec3 <$> (#peek aiVector3D, x) p
<*> (#peek aiVector3D, y) p
<*> (#peek aiVector3D, z) p
Ahora puede pensar en cuatro formas agradables para escribir ese código, todo estrechamente relacionados:
peek p = Vec3 <$> io1 <*> io2 <*> io3
peek p = liftA3 Vec3 io1 io2 io3
peek p = return Vec3 `ap` io1 `ap` io2 `ap` io3
peek p = liftM3 Vec3 io1 io2 io3
en cuenta que lo que pido sobre el código monádico que no requiere nada más allá lo que Applicative
proporciona. ¿Cuál es la forma preferida de escribir este código? ¿Debo usar Applicative
para enfatizar lo que hace el código, o debo usar Monad
porque podría (?) Tener optimizaciones sobre Applicative
?
La pregunta es algo complicado por el hecho de que sólo hay [liftA..liftA3]
y [liftM..liftM5]
pero tengo varios registros con más de tres o cinco miembros, por lo que si decido ir con lift{A,M}
que perder un poco de coherencia, ya que tendría que utilizar un método diferente para los registros más grandes.
La consistencia habla por 'ap' o' <*> '. Lo que eliges es en gran medida una cuestión de gusto. Mi preferencia (y tengo la impresión de que no es solo mía) es '<*>'. –