Pregunta

Voy a enseñar un curso de división baja en estructuras discretas. He seleccionado el libro de texto Estructuras discretas, lógica y computabilidad en parte porque contiene ejemplos y conceptos que son propicios para la implementación con un lenguaje de programación funcional. (También creo que es un buen libro de texto).

Quiero un lenguaje de PF fácil de entender para ilustrar los conceptos de DS y que los estudiantes puedan usar. La mayoría de los estudiantes solo habrán tenido uno o dos semestres de programación en Java, en el mejor de los casos. Después de ver Scheme, Erlang, Haskell, Ocaml y SML, me decidí por Haskell o Standard ML. Me inclino por Haskell por los motivos que se describen a continuación, pero me gustaría conocer la opinión de quienes son programadores activos en uno u otro.

  • Tanto Haskell como SML tienen una coincidencia de patrones que hace que la descripción de un algoritmo recursivo sea muy fácil.
  • Haskell tiene una buena comprensión de listas que coinciden perfectamente con la forma en que dichas listas se expresan matemáticamente.
  • Haskell tiene una evaluación perezosa. Excelente para construir listas infinitas utilizando la técnica de comprensión de listas.
  • SML tiene un intérprete verdaderamente interactivo en el que las funciones se pueden definir y utilizar. En Haskell, las funciones deben definirse en un archivo separado y compilarse antes de usarse en el shell interactivo.
  • SML proporciona una confirmación explícita del argumento de la función y los tipos de retorno en una sintaxis que es fácil de entender. Por ejemplo: val foo = fn: int * int - > En t. La sintaxis implícita de curry de Haskell es un poco más obtusa, pero no totalmente ajena. Por ejemplo: foo :: Int - > Int - > Int.
  • Haskell usa enteros de precisión arbitraria por defecto. Es una biblioteca externa en SML / NJ. Y SML / NJ trunca la salida a 70 caracteres de forma predeterminada.
  • La sintaxis lambda de Haskell es sutil: utiliza una sola barra invertida. SML es más explícito. Sin embargo, no estoy seguro de si alguna vez necesitaremos lambda en esta clase.

Esencialmente, SML y Haskell son aproximadamente equivalentes. Me inclino por Haskell porque me encantan las listas de comprensión y las listas infinitas de Haskell. Pero me preocupa que la gran cantidad de símbolos en la sintaxis compacta de Haskell pueda causar problemas a los estudiantes. Por lo que he recopilado leyendo otras publicaciones en SO, Haskell no se recomienda para principiantes que comienzan con FP. Pero no vamos a construir aplicaciones completas, solo probaremos algoritmos simples.

¿Qué piensas?


Editar: al leer algunas de tus excelentes respuestas, debo aclarar algunos de mis puntos importantes.

En SML, no hay una distinción sintáctica entre definir una función en el intérprete y definirla en un archivo externo. Digamos que quieres escribir la función factorial. En Haskell puede poner esta definición en un archivo y cargarla en GHCi:

fac 0 = 1
fac n = n * fac (n-1)

Para mí, eso es claro, conciso y coincide con la definición matemática del libro. Pero si desea escribir la función en GHCi directamente, debe utilizar una sintaxis diferente:

let fac 0 = 1; fac n = n * fac (n-1)

Cuando se trabaja con intérpretes interactivos, desde una perspectiva de enseñanza es muy, muy útil cuando el estudiante puede usar el mismo código tanto en un archivo como en la línea de comandos.

Por " confirmación explícita de la función, " Me refiero a que al definir la función, SML de inmediato le dice el nombre de la función, los tipos de argumentos y el tipo de retorno. En Haskell tienes que usar el comando : type y luego obtienes una notación de curry algo confusa.

Una cosa más interesante sobre Haskell: esta es una definición de función válida:

fac 0 = 1
fac (n+1) = (n+1) * fac n

Nuevamente, esto coincide con una definición que podrían encontrar en el libro de texto. No puedo hacer eso en SML!

¿Fue útil?

Solución

Por mucho que amo a Haskell, estas son las razones por las que preferiría el SML para una clase en matemáticas discretas y estructuras de datos (y la mayoría de las otras clases de principiantes):

  • Los costos de tiempo y espacio de los programas de Haskell pueden ser muy difíciles de predecir, incluso para los expertos. SML & nbsp; ofrece formas mucho más limitadas de explotar la máquina.

  • La sintaxis para la definición de funciones en un intérprete interactivo es idéntica a la sintaxis utilizada en un archivo, por lo que puede cortar y pegar.

  • Aunque la sobrecarga del operador en SML es totalmente falsa, también es simple. Va a ser difícil enseñar una clase completa en Haskell sin tener que entrar en clases de tipo.

  • El alumno puede realizar la depuración utilizando print . (Aunque, como señala un comentarista, es posible obtener casi el mismo efecto en Haskell usando Debug.Trace.)

  • Las estructuras de datos infinitas hacen volar la mente de las personas. Para los principiantes, es mejor que definan un tipo de flujo completo con celdas ref. Y thunk, para que sepan cómo funciona:

    datatype 'a thunk_contents = UNEVALUATED of unit -> 'a
                               | VALUE of 'a
    type 'a thunk = 'a thunk_contents ref
    val delay : (unit -> 'a) -> 'a thunk
    val force : 'a thunk -> 'a
    

    Ahora ya no es mágico, y puedes ir de aquí a las secuencias (listas infinitas).

  • El diseño no es tan simple como en Python y puede ser confuso.

Hay dos lugares donde Haskell tiene una ventaja:

  • En el núcleo Haskell puede escribir la firma de tipo de una función justo antes de su definición. Esto es de gran ayuda para los estudiantes y otros principiantes. Simplemente no hay una buena manera de lidiar con las firmas de tipo en SML.

  • Haskell tiene una mejor sintaxis concreta. La sintaxis de Haskell es una mejora importante sobre la sintaxis de ML. He & nbsp; he escrito una breve nota sobre cuándo usar paréntesis en un Programa de ML ; esto ayuda un poco.

Finalmente, hay una espada que corta en ambos sentidos:

  • El código de Haskell es puro por defecto, por lo que es poco probable que sus estudiantes tropiecen con construcciones impuras (mónada IO, mónada estatal) por accidente. Pero de la misma manera, no pueden imprimir, y si desea realizar I / O, entonces al mínimo debe explicar la notación de do y return es confuso.

En un tema relacionado, aquí hay algunos consejos para la preparación de su curso: no pase por alto Estructuras de datos puramente funcionales por Chris Okasaki. Incluso si no hace que sus estudiantes lo usen, definitivamente querrá tener una copia.

Otros consejos

Enseñamos Haskell a los primeros años en nuestra universidad. Mis sentimientos sobre esto están un poco mezclados. Por un lado, enseñar a Haskell a los primeros años significa que no tienen que desaprender el estilo imperativo. Haskell también puede producir un código muy conciso que las personas que antes tenían Java pueden apreciar.

Algunos problemas que he notado en los estudiantes a menudo tienen:

  • La coincidencia de patrones puede ser un poco difícil, al principio. Inicialmente, los estudiantes tuvieron algunos problemas al ver cómo se relacionan la construcción de valores y la comparación de patrones. También tuvieron algunos problemas para distinguir entre abstracciones. Nuestros ejercicios incluyeron funciones de escritura que simplifican la expresión aritmética y algunos estudiantes tuvieron dificultades para ver la diferencia entre la representación abstracta (por ejemplo, Const 1 ) y la representación en lenguaje meta ( 1 ) .

    Además, si se supone que sus estudiantes deben escribir las funciones de procesamiento de listas, tenga cuidado al señalar la diferencia entre los patrones

    []
    [x]
    (x:xs)
    [x:xs]
    

    Dependiendo de la cantidad de programación funcional que quiera enseñarles en el camino, puede darles algunas funciones de biblioteca y dejar que jueguen con eso.

  • No enseñamos a nuestros estudiantes sobre funciones anónimas, simplemente les contamos sobre las cláusulas donde . Para algunas tareas esto fue un poco detallado, pero funcionó bien de otra manera. Tampoco les contamos sobre solicitudes parciales; esto es probablemente bastante fácil de explicar en Haskell (debido a su forma de tipos de escritura), por lo que podría valer la pena mostrarles.

  • Descubrieron rápidamente las listas de comprensión y las prefirieron a las funciones de orden superior como filter , map , zipWith .

  • Creo que nos perdimos un poco de enseñarles cómo dejar que guíen sus pensamientos por tipos. Sin embargo, no estoy muy seguro de si esto es útil para los principiantes o no.

  • Los mensajes de error generalmente no son muy útiles para los principiantes, ya que pueden necesitar ayuda con ellos. No lo he probado, pero hay un compilador de Haskell dirigido específicamente a los recién llegados, principalmente a través de mejores mensajes de error: Helium

  • Para los programas pequeños, cosas como posibles fugas de espacio no fueron un problema.

En general, Haskell es un buen lenguaje de enseñanza, pero hay algunas trampas. Dado que los estudiantes se sienten mucho más cómodos con la comprensión de listas que con las funciones de orden superior, este podría ser el argumento que necesita. No sé cuánto tiempo dura tu curso o cuánta programación quieres enseñarles, pero planea algún tiempo para enseñarles conceptos básicos: lo necesitarán.

BTW,

  

# SML tiene un verdadero interactivo   intérprete en el que las funciones pueden ser   tanto definidos como utilizados. En Haskell,   Las funciones deben ser definidas en una   archivo separado y compilado antes   siendo utilizado en el shell interactivo.

Es inexacto. Utilice GHCi:

Prelude> let f x = x ^ 2
Prelude> f 7
49
Prelude> f 2
4

También hay buenos recursos para Haskell en educación en haskell.org edu. Página, con experiencias de diferentes profesores. http://haskell.org/haskellwiki/Haskell_in_education

Finalmente, podrás enseñarles el paralelismo de múltiples núcleos solo por diversión, si usas Haskell :-)

Muchas universidades enseñan a Haskell como primer lenguaje funcional o incluso como primer lenguaje de programación, por lo que no creo que esto sea un problema.

Después de haber hecho parte de la enseñanza en uno de estos cursos, no estoy de acuerdo con que las posibles confusiones que usted identifique sean tan probables. Las fuentes más probables de confusión temprana son los errores de análisis causados ??por un diseño incorrecto y los mensajes misteriosos sobre las clases de tipos cuando los literales numéricos se usan incorrectamente.

También estoy en desacuerdo con cualquier sugerencia de que Haskell no sea recomendable para principiantes que comienzan con FP. Sin duda, es el enfoque del Big Bang en el sentido de que los lenguajes estrictos con mutación no lo son, pero creo que es un enfoque muy válido.

  
      
  • SML tiene un intérprete verdaderamente interactivo en el que las funciones se pueden definir y utilizar. En Haskell, las funciones deben definirse en un archivo separado y compilarse antes de usarse en el shell interactivo.
  •   

Si bien los abrazos pueden tener esa limitación, GHCi no:

$ ghci
GHCi, version 6.10.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
Prelude> let hello name = "Hello, " ++ name
Prelude> hello "Barry"
"Hello, Barry"

Hay muchas razones por las que prefiero GHC (i) en lugar de Abrazos, esta es solo una de ellas.

  
      
  • SML proporciona una confirmación explícita del argumento de la función y los tipos de retorno en una sintaxis que es fácil de entender. Por ejemplo: val foo = fn: int * int - > En t. La sintaxis implícita de curry de Haskell es un poco más obtusa, pero no totalmente ajena. Por ejemplo: foo :: Int - > Int - > Int.
  •   

SML tiene lo que tú llamas " currícito implícito " la sintaxis también.

$ sml
Standard ML of New Jersey v110.69 [built: Fri Mar 13 16:02:47 2009]
- fun add x y = x + y;
val add = fn : int -> int -> int
  

Esencialmente, SML y Haskell son aproximadamente equivalentes. Me inclino por Haskell porque me encantan las listas de comprensión y las listas infinitas de Haskell. Pero me preocupa que la gran cantidad de símbolos en la sintaxis compacta de Haskell pueda causar problemas a los estudiantes. Por lo que he recopilado leyendo otras publicaciones en SO, Haskell no se recomienda para principiantes que comienzan con FP. Pero no vamos a construir aplicaciones completas, solo probaremos algoritmos simples.

Me gusta usar Haskell mucho más que SML, pero aún así enseñaría SML primero.

  • Los pensamientos de nominolo en segundo lugar, las comprensiones de listas do parecen hacer que los estudiantes no puedan acceder a algunas funciones de orden superior.
  • Si quieres la pereza y las listas infinitas, es instructivo implementarlo explícitamente.
  • Debido a que SML se evalúa con entusiasmo, el modelo de ejecución es mucho más fácil de comprender y " a través de printf " Funciona mucho mejor que en Haskell.
  • El sistema de tipos de SML también es más simple. Si bien es probable que su clase no los use, las clases de tipos de Haskell siguen siendo un obstáculo adicional para superar: lograr que comprendan la distinción de 'a en lugar de ' 'a en SML es lo suficientemente fuerte.

La mayoría de las respuestas fueron técnicas, pero creo que deberías considerar al menos una que no lo sea: Haskell (como OCaml), en este momento, tiene una comunidad más grande que lo usa en una gama más amplia de contextos. También hay una gran base de datos de bibliotecas y aplicaciones escritas con fines de lucro y diversión en Hackage . Ese puede ser un factor importante para que algunos de sus estudiantes utilicen el idioma una vez que finalice su curso, y quizás intenten otros idiomas funcionales (como el estándar ML) más adelante.

Me sorprende que no esté considerando OCaml y F # dado que abordan muchas de sus preocupaciones. ¿Seguramente los entornos de desarrollo decentes y útiles son una alta prioridad para los estudiantes? SML está muy por detrás y F # está muy por delante de todos los demás FPL a ese respecto.

Además, tanto OCaml como F # tienen listas de comprensión.

Haskell. Me adelanto en mi clase de algos / teoría en CS debido a las cosas que aprendí de usar Haskell. Es un lenguaje tan completo, y le enseñará un montón de CS, simplemente usándolo .

Sin embargo, SML es mucho más fácil de aprender. Haskell tiene características como la perezosa evaluación y las estructuras de control que lo hacen mucho más poderoso, pero con el costo de una curva de aprendizaje empinada (ish). SML no tiene tal curva.

Dicho esto, la mayoría de Haskell estaba desaprendiendo cosas de lenguajes menos científicos / matemáticos como Ruby, ObjC o Python.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top