tipos sobrecarga polimorfismo operadores logicos inteligencia ejemplos ejemplo datos clausula artificial haskell polymorphism

operadores - ¿Cómo maneja Haskell la sobrecarga de polimorfismo?



polimorfismo en haskell (6)

Aquí tienes un ejemplo simple que combina

  • Polimorfismo ad hoc (sobrecarga) : misma función con comportamiento diferente para diferentes tipos (por medio de clases de tipo Haskell)

  • Polimorfismo paramétrico : la misma función con el mismo comportamiento para diferentes tipos (por medio de una función parametrizada de tipo. En principio, el tipo no importa, pero usamos clases de tipo para restringir los tipos aceptables).

Código:

import Data.Char class MyTypeFamily t where f1 :: t -> Int f2 :: t -> Int instance MyTypeFamily Int where f1 x = x*x f2 x = x+x instance MyTypeFamily Char where f1 x = (ord x) * (ord x) f2 x = (ord x) + (ord x) instance MyTypeFamily Bool where f1 x | x = 10 | otherwise = 10 f2 x | x = 100 | otherwise = -100 -- ............................................................... -- using f1, f2 as "overloaded" functions ("ad-hoc polymorphism) -- (the algorithm for f1, f2 is chosen depending on their type) -- -- using fun as polymorphic (parametric polymorphic function) -- the algorithm of fun is always the same but it works on -- different types fun :: (MyTypeFamily t) => t -> Int fun x = (f1 x) + (f2 x) -- ............................................................... -- ............................................................... main = do print $ fun ''J'' print $ fun True print $ fun False print $ fun (8 :: Int)

Tengo una pregunta sobre el polimorfismo de Haskell.

Como he aprendido, hay dos tipos de polimorfismo:

  1. Parametric : donde no se especifica el tipo de entrada.

    Ejemplo:

    functionName :: [a] -> a

  2. Sobrecarga : como programación imperativa, es decir, pasar diferentes argumentos a la misma función.

Mi problema es: ¿cómo maneja Haskell la sobrecarga ?


Básicamente, la anulación es bastante diferente en Haskell, aunque puedes hacer algo similar.

I. Usa las clases como respuesta seleccionada.

class YesNo a where yesno :: a -> Bool

Tienes que implementarlo usando una instancia, y luego puedes usarlo así:

> yesno $ length [] False > yesno "haha" True > yesno "" False > yesno $ Just 0 True > yesno True True ghci> yesno EmptyTree False > yesno [] False > yesno [0,0,0] True

http://learnyouahaskell.com/making-our-own-types-and-typeclasses

II. Utilice la coincidencia de patrones del constructor de tipos, como:

data Shape = Circle Float Float Float | Rectangle Float Float Float Float surface :: Shape -> Float surface (Circle _ _ r) = pi * r ^ 2 surface (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs $ y2 - y1)

Y luego puedes usarlos así:

> surface $ Circle 10 20 10 314.15927 > surface $ Rectangle 0 0 100 100 10000.0

http://learnyouahaskell.com/making-our-own-types-and-typeclasses

III. Tenga la función "sobrecargada" en el módulo separado, pero tendrá que prefijar el nombre de importación o el nombre de importación calificado

http://learnyouahaskell.com/modules


En algunos idiomas, la sobrecarga significa usar el mismo nombre para varias funciones que proporcionan una funcionalidad similar pero diferente, por lo que puede intentarlo

split :: String -> [String] -- splits on whitespace split :: Char -> String -> [String] -- splits on the given character split :: [Char] -> String -> [String] -- splits on any of the given characters split :: (Char -> Bool) -> String -> [String] -- splits using a function that tells you when

lo que le daría el error de Duplicate type signature que está recibiendo.

Haskell no hace este tipo de sobrecarga, y un programador de Haskell le daría estos nombres diferentes:

words :: String -> [String] -- splits on whitespace splitOn :: Char -> String -> [String] -- splits on the given character splitsOn :: [Char] -> String -> [String] -- splits on any of the given characters splitWith :: (Char -> Bool) -> String -> [String] -- splits using a function that tells you when

La razón por la que Haskell no permite el tipo de sobrecarga que creo que estás preguntando es porque realmente no te permite hacer nada que no puedas hacer sin él, y permitirlo hace que sea casi imposible Tipos más avanzados de sobrecarga. La sobrecarga de Haskell es una herramienta muy poderosa; Infórmese sobre las clases de tipos y las clases de constructores para comenzar.

En realidad, dado que a los programadores de String = [Char] y Haskell les encanta la reutilización del código, es mucho más probable que escriban:

words :: String -> [String] -- splits on whitespace splitOn :: Eq a => a -> [a] -> [[a]] -- splits on the given item splitsOn :: Eq a => [a] -> [a] -> [[a]] -- splits on any of the given items splitWith :: (a -> Bool) -> [a] -> [[a]] -- splits using a function that tells you when

Aquí la Eq a es un ejemplo de un tipo de sobrecarga que Haskell permite, donde splitOn le permitirá dividir cualquier lista siempre que los elementos puedan ser comparados por igualdad (es decir, Haskell le permite definir su propia noción de igualdad). Puede usar esto para dividir una Cadena o, por ejemplo, una lista de Cadenas, pero no puede dividir una lista de funciones porque no puede verificar dos funciones para ver si son iguales. splitWith es un ejemplo de Haskell que le permite tratar una función como la mayoría de los demás datos: ¡puede pasar una como argumento!

[Nota 1: las words son una función estándar, splitWith está en una biblioteca con una tipografía ligeramente diferente.]
[Nota 2: si realmente desea escribir estas funciones, aquí tiene cómo:

splitWith isSplitter list = case dropWhile isSplitter list of [] -> [] thisbit -> firstchunk : splitWith isSplitter therest where (firstchunk, therest) = break isSplitter thisbit -- words = splitWith isSpace -- not needed, standard function from the Prelude splitOn c = splitWith (== c) -- notice I passed == in an argument! splitsOn chars = splitWith (`elem` chars)

]


Especifica el tipo de firma de su función en la clase de tipo original, luego crea varias instancias de esa función para las que escribió la firma. Por lo tanto, en el ejemplo publicado por Hammar, se puede pensar que un polimórfico es, y el tipo especificado en cada instancia (por ejemplo, Fooable Bool) como el tipo de (en este caso a es un Bool). Entonces, cuando llama a la función foo con un valor Bool, se llama a la instancia de Fooable para un valor Bool.

Por cierto, puede poner múltiples funciones en la clase de tipo, y puede definir funciones en términos de otras funciones definidas también.

p.ej

class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y)

Puede que no sea obvio aquí, pero si define una instancia de Eq, solo necesita definir == o / =, no ambas, ya que están definidas en términos de la otra.



La sobrecarga en Haskell se realiza mediante clases de tipo. Por ejemplo, supongamos que desea sobrecargar una función foo que devuelve un Int :

class Fooable a where foo :: a -> Int instance Fooable Int where foo = id instance Fooable Bool where foo _ = 42

Sin embargo, son más poderosos que los mecanismos de sobrecarga que se encuentran en la mayoría de los idiomas. Por ejemplo, puede sobrecargar en el tipo de retorno:

class Barable a where bar :: Int -> a instance Barable Int where bar x = x + 3 instance Barable Bool where bar x = x < 10

Para más ejemplos, eche un vistazo a las clases de tipos predefinidas en Haskell.