Haskell accessors for non-existing records -


i learning haskell , discovering 'accessors' data members. let's assume have dummy 2d vertex information, 1 type has color, other has texture coordinate (tc):

data svertex = vertexc (float, float) int          | vertextc (float, float) (float, float)          deriving(show) 

one tedious way create accessors records write functions patterns:

position (vertexc (x,y) c ) = (x,y) position (vertextc (x,y) c ) = (x,y) tc (vertextc _ tc) = tc color :: svertex -> int color (vertexc _ c) = c 

now, positive feature add accessors ('color' , 'tc') ones don't have 'color' or 'tc' :

position (vertexc (x,y) c ) = (x,y) position (vertextc (x,y) c ) = (x,y) -- no header, here... still works tc (vertextc _ tc) = tc tc (vertexc _ _) = (0,0) -- returns if field doesn't exist color :: svertex -> int color (vertexc _ c) = c color (vertextc _ _) = 0 -- return if field doesn't exist 

it allows me give default 0 values vertices don't have texture-coords or color 0 vertices don't have color... good...

now, question: reading there nice way give accessor names right data declaration. in case here (using 'prime' avoid name conflict):

data svertex' = vertexc' {     position'   :: (float, float),     color'      :: int     }     | vertextc' {     position'   :: (float, float),     tc'         :: (float, float)     } deriving(show) 

this allows me reach same goal: "position' ", "tc' " , "color' " accessors created me!

however: didn't find way give default accessor fields don't exist. example when requesting tc on 'vertexc'; or requesting color on vertextc... on first approach, make happen. in convenient second approach, fear not possible. when try add other function pattern

color' (vertextc' _ _) = 0 

the compiler tells me "multiple declarations of ‘color’ etc.". , seems because second declaration not done following previous implicit 1 created compiler...

do know workaround ?

as have found out, records don't mix sum types (that is, types multiple constructors), lead unpleasant partial accessors can't rid of. 1 alternative using sum type fields require it, rather making svertex whole sum type. way, many nice accessors possible while avoiding partial ones.

data vertexpaint = vertexc int | vertextc (float, float)     deriving (show)  data svertex = svertex     { position :: (float, float)     , paintjob :: vertexpaint     } deriving (show) 

if want color function, still have define separately, in first attempt. (here use maybe int result, more not safer bet returning arbitrary default.)

color :: svertex -> maybe int color v = case paintjob v of     vertexc c -> c     vertextc _ -> nothing 

as alec suggests, lens library provides plenty of tools deal sort of situation in more convenient ways. in case, types defined in answer work lens.


Comments

Popular posts from this blog

java - SSE Emitter : Manage timeouts and complete() -

jquery - uncaught exception: DataTables Editor - remote hosting of code not allowed -

java - How to resolve error - package com.squareup.okhttp3 doesn't exist? -