2011-01-22 25 views
5

Entonces, tengo una función con múltiples definiciones (guardias), y dependiendo de cuál coincida, estoy tratando de que devuelva un (a, b) o [ (a, b)], sin embargo, el compilador está arrojando errores porque son de tipos diferentes. Estaba intentando usar O bien para resolver esto, pero probablemente no lo estoy usando bien: P. ¿alguna ayuda?Cómo obtener una función para devolver diferentes tipos

+1

No se puede hacer eso directamente porque el tipo de devolución de la función se debe conocer en tiempo de compilación, mientras que las protecciones se combinan en el tiempo de ejecución. ¿Pero está seguro de que realmente desea devolver un tipo diferente? Si tiene la intención de coincidir con el patrón en el resultado para distinguir los dos casos, cualquiera está bien. ¿O tal vez una lista singleton servirá en el primer caso? ¿Puedes proporcionar más detalles sobre lo que vas a hacer? – b0fh

+0

http://paste.pocoo.org/show/325066/ es mi función hasta ahora –

+0

que es como leer un hechizo mágico. ¿Qué se supone que significa? – luqui

Respuesta

9

Either - o un tipo de datos a medida equivalente a ella - es el único forma de hacer esto. Aquí está un ejemplo tonto:

stuff :: Int -> Either (Int,Int) [(Int,Int)] 
stuff 0 = Left (0, 0) 
stuff n = Right [ (x,x) | x <- [0..n] ] 

Entonces cuando alguien llama a esta función, que puede coincidir con el patrón para averiguar cuál de los dos tipos ha devuelto:

foo n = case stuff n of 
      Left (a,b) -> ... 
      Right pairs -> ... 

Sin embargo, sin saber nada acerca de su problema, en En general, recomendaría pensar un poco más sobre el significado de su función. Qué se necesita, ¿qué devuelve? Se preciso, matemático. Mientras más simple sea la respuesta, más fácilmente funcionará esta función con el resto de su programa y los conceptos de Haskell. Para mí, en tales descripciones, Either rara vez aparece. ¿Cómo se pueden unificar los dos resultados? Tal vez solo devuelva la lista única [(a,b)] en lugar de Left (a,b), si eso tiene sentido para su función.

Haskell no funciona bien con las funciones que intentan ser demasiado inteligentes, del tipo que se puede utilizar desde Python o jQuery. Manténgalo tonto y preciso: obtenga su complejidad de componiendo estas piezas simples. Si tiene curiosidad acerca de esto, haga otra pregunta con más detalles sobre su problema, lo que está tratando de lograr y por qué desea que funcione de esa manera. Perdón por la predicación :-)

+0

Permítanme agregar que la propiedad que queremos del sistema tipo es la de * preservation *: Hablando en términos generales si tenemos el tipo 'stuff :: Int -> (Int, Int) 'entonces una llamada a' cosas 7 'decir reduciría a '[(x, x) | x <- [0..n] 'en el ejemplo que tiene el tipo' [(Int, Int)] '. Esto es diferente del tipo de devolución proclamado de 'cosas' y, por lo tanto, no se conservará el tipo.Si confiamos en el sistema de tipos para cualquier cosa, esta discrepancia debe ser descartada. Entonces, el verificador de tipos rechaza que nuestro programa esté mal escrito. –

0

Las funciones en Haskell solo pueden devolver un tipo, por lo que Cualquiera funcionará para usted, ya que su función devolvería el tipo O bien (a, b) [(a.b)].

No estoy seguro de lo que salió mal con la forma en que está utilizando cualquier pero aquí es un simple ejemplo de su uso:

test a b = 
    if a == True 
    then Left (a,b) 
    else Right [(a,b)] 
+0

así que aquí está mi función ahora: http://paste.pocoo.org/show/325090/ aquí está el error: http: //paste.pocoo. org/show/325093/ –

+0

@Chris 'Right lgst i' debe ser' Right (lgst i) '. – dave4420

+0

ok, así que http://paste.pocoo.org/show/325143/ funciona, sin embargo, los últimos dos guardias deben tener un aspecto similar a http://paste.pocoo.org/show/325144/, que me da: http://paste.pocoo.org/show/325145/ –

Cuestiones relacionadas