Why is the reverse function in Haskell not working? - recursion

So I'm am supposed to return a list of Int using recursion in haskell. I am creating the list correctly but the numbers in the list are out of order. I tried using the reverse function to get the correct output but it doesn't seem to be doing anything. This is the function and what the output is supposed to be
numlist 0
[0]
numlist 4
[0,1,2,3,4]
numlist (-5)
program error: illegal argument
This is my function
numList :: Int -> [Int]
numList n | n < 0 = error "program error: illegal argument"
| n == 0 = reverse([n])
| otherwise = n:numList(n-1)

Related

Errors while iterating and processing the split string in recursive functions

Let's say we have a string
"+x1 +x2 -x3
+x4 +x5 -x6
..."
and a type formula:
type formula =
| Bot
| Top
| Atom of string
| Imp of (formula * formula)
| Or of (formula * formula)
| And of (formula * formula)
| Not of formula
let atom x = Atom x
(aka predicate logic)
and we want to:
Create a function which takes one line, splits it and turns it into disjunction using the formula type. (sort of like Or(Atom "x1", Atom "x2", Not Atom "x3") if we give the first line as an input)
I've written this:
let string_to_disj st =
let lst = Str.split (Str.regexp " \t") st in
let rec total lst =
match lst with
| [] -> Or (Bot, Bot) (*Is this correct btw?*)
| h :: t -> Or (string_to_lit h, total t);;
where
let string_to_lit =
match String.get s 0 with
| '+' -> atom (String.sub s 1 (String.length s-1))
| '-' -> Not(atom(String.sub s 1 (String.length s-1)))
| _ -> atom(s);;
However, string_to_disj raises a syntax error at line
| h :: t -> Or (string_to_lit h, total t)
What have I done wrong?
You have let rec total lst but you have no matching in. Every let requires a matching in. (Except at the top level of a module where it is for defining exported symbols of the module).
Also note that you are defining a function named total but you have no calls to the function except the one recursive call.

Find all even number in array in purescript but getting type mismatch error

I am solving a problem in which I have to count all the even numbers in an array in purescript. I have written down code but I am facing type mismatch error.
import Data.Array (null)
import Data.Array.Partial (tail,head)
import Partial.Unsafe (unsafePartial)
import Math
iseven :: Int -> Boolean
iseven a = mod a 2 == 0
len :: forall a. Array a -> Int
len arr =
if null arr
then 0
else
if iseven unsafePartial head arr
then 1 + len (unsafePartial tail arr)
else len (unsafePartial tail arr)
But I am getting an error.
Error found:
in module $PSCI
at :6:18 - 6:40 (line 6, column 18 - line 6, column 40)
Could not match type
a1
with type
Int
while checking that type t0
is at least as general as type Int
while checking that expression (unsafePartial head) arr
has type Int
in binding group len
where a1 is a rigid type variable
bound at (line 0, column 0 - line 0, column 0)
t0 is an unknown type
I am new to purescript so I am not able to understand the error.
When you write unsafePartial head arr, that means "apply function unsafePartial to two arguments, first argument head and second argument arr, but this is not what you want to do.
What you want to do is first calculate head arr, and only then apply unsafePartial to the result of that.
To achieve this, use parentheses:
unsafePartial (head arr)
Or the $ operator:
unsafePartial $ head arr
After you have fixed that, the next error you're getting is about what iseven expects as argument and what you're passing to it. The signature of len says forall a. Array a ->, which means "I will work with arrays of any type", but in reality it's trying to pass an element of that array to iseven, which expects an Int. So your function promised to work with anything, but actually wants Int.
To fix, make the signature tell the truth: the function wants an array of Ints:
len :: Array Int -> Int

Invalid_argument "String.sub / Bytes.sub"

I have a small problem on an exercice that i'm doing.
I try to recursively count vowels in a String but i have this strange error popping.
Can someone explain me why ?
let rec nb_voyelle = function chaine ->
if chaine == "" then
0
else
let length = (String.length chaine)-1 in
let p_length = String.sub chaine 0 length in
match chaine.[length] with
| 'a' | 'e' | 'i' | 'o' | 'u' | 'y' -> 1 + nb_voyelle p_length
| _ -> 0 + nb_voyelle p_length
;;
Answer is i used "==" to compare the string in my final case which is not the good pervasive to test equality between two elements.
As such, the case (String.sub "" 0 -1) happens and the function fail raising this error.

How to create a cached recursive type?

open System
open System.Collections.Generic
type Node<'a>(expr:'a, symbol:int) =
member x.Expression = expr
member x.Symbol = symbol
override x.GetHashCode() = symbol
override x.Equals(y) =
match y with
| :? Node<'a> as y -> symbol = y.Symbol
| _ -> failwith "Invalid equality for Node."
interface IComparable with
member x.CompareTo(y) =
match y with
| :? Node<'a> as y -> compare symbol y.Symbol
| _ -> failwith "Invalid comparison for Node."
type Ty =
| Int
| String
| Tuple of Ty list
| Rec of Node<Ty>
| Union of Ty list
type NodeDict<'a> = Dictionary<'a,Node<'a>>
let get_nodify_tag =
let mutable i = 0
fun () -> i <- i+1; i
let nodify (dict: NodeDict<_>) x =
match dict.TryGetValue x with
| true, x -> x
| false, _ ->
let x' = Node(x,get_nodify_tag())
dict.[x] <- x'
x'
let d = Dictionary(HashIdentity.Structural)
let nodify_ty x = nodify d x
let rec int_string_stream =
Union
[
Tuple [Int; Rec (nodify_ty (int_string_stream))]
Tuple [String; Rec (nodify_ty (int_string_stream))]
]
In the above example, the int_string_stream gives a type error, but it neatly illustrates what I want to do. Of course, I want both sides to get tagged with the same symbol in nodify_ty. When I tried changing the Rec type to Node<Lazy<Ty>> I've found that it does not compare them correctly and each sides gets a new symbol which is useless to me.
I am working on a language, and the way I've dealt with storing recursive types up to now is by mapping Rec to an int and then substituting that with the related Ty in a dictionary whenever I need it. Currently, I am in the process of cleaning up the language, and would like to have the Rec case be Node<Ty> rather than an int.
At this point though, I am not sure what else could I try here. Could this be done somehow?
I think you will need to add some form of explicit "delay" to the discriminated union that represents your types. Without an explicit delay, you'll always end up fully evaluating the types and so there is no potential for closing the loop.
Something like this seems to work:
type Ty =
| Int
| String
| Tuple of Ty list
| Rec of Node<Ty>
| Union of Ty list
| Delayed of Lazy<Ty>
// (rest is as before)
let rec int_string_stream = Delayed(Lazy.Create(fun () ->
Union
[
Tuple [Int; Rec (nodify_ty (int_string_stream))]
Tuple [String; Rec (nodify_ty (int_string_stream))]
]))
This will mean that when you pattern match on Ty, you'll always need to check for Delayed, evaluate the lazy value and then pattern match again, but that's probably doable!

Cant figure out what Error means and how to solve it

Here is the error code I have:
Characters 2004-2008
Error: The type constructor list expects 1 argument(s),
but is here applied to 0 argument(s)
Here is the Ocaml code I have written:
let createHuffmanTree (s:string) = match s with
| "" -> Empty (*Return an empty huffman tree ifstring is empty*)
| _ -> let rec ca (l: list) (a: huffman) = match l with (*ERROR SHOULD BE ON THIS LINE*)
| [] -> a (*If list is [] return the huffman tree*)
| x,_ -> fold_left (ca) l level(leaf(x),a) (*For all the ellement of the list create a level and corresponding leaf*)
in ca listFreq(explode(s)) Empty (*Start with an empty tree*)
Note:
explode take a string return it as a list of char
ex:
# explode "Test";;
- : char list = ['T'; 'e'; 's'; 't']
listFreq take the list from explode and return a pair of char * int being the char and the number of time it is found in the list return by explode
ex:
# listeFreq (explode "AABCAABADBACAAB");;
- : (char * int) list = [('A', 8); ('B', 4); ('C', 2); ('D', 1)]
The Huffman Tree I am trying to create take a string (for exemple "AAABBC")
and do this:
level
| |
v v
leaf A level
| |
v v
leaf B leaf C
The tree could also be Empty
Question:
I have no idea how to solve the error code. Could someone point out a solution?
I suppose that instead of (l: list), you should have something like (l: 'a list).

Resources