Spliting a list of strings in OCaml - string

I have a list as let a = ["q0,x";"q1,y"]; which is of type string list.
I want to make it as [("q0","x");("q1","y")]; which is a list of (string * string) tuples.
How do I do that??

You can use module Str and the function split :
let split =
List.map (fun str ->
match Str.split (Str.regexp ",") str with
| a :: b :: _ -> a, b
| _ -> assert false (* should not happen *))

Related

can i use a string as a whole string after cutting it to head and tails (a:as) and using recursion on it in Haskell?

I am trying to use every character in the string in a function i have (that uses only one Char) but i am also trying to use that same string as a whole in the same recursive function to compare it to indvidual characters in another string (using elem). Is there a way i can use that string heads and tails and also the whole string, so that the string will not be cut after every recursion?
Code:
checkTrue :: TrueChar -> Char -> [Char] -> TruthValue
checkTrue a b c
| a == IsTrue b = AbsoluteTrue
| (a == IsFalse b) && (b `elem` c) = PartialTrue
| otherwise = NoneTrue
checkTruths :: [TrueChar] -> [Char] -> [TruthValue]
checkTruths [][] = []
checkTruths (a:as) (b:bs) = checkTrue a b (removeAbsoluteTrue (a:as) (b:bs)): checkTruths as bs
{- This is the line,
i wanted to use b as a string and also as b:bs. is this possible? -}
checkTruths _ _ = [NoneTrue]
You want an as-pattern, as documented in Section 3.17.1 of the Haskell 2010 report.
Patterns of the form var#pat are called as-patterns, and allow one to
use var as a name for the value being matched by pat. For example,
case e of { xs#(x:rest) -> if x==0 then rest else xs }
is equivalent
to:
let { xs = e } in
case xs of { (x:rest) -> if x==0 then rest else xs }
In your function, you'd write
checkTruths alla#(a:as) allb#(b:bs) = checkTrue a b (removeAbsoluteTrue alla allb): checkTruths as bs

F# - Remove duplicate characters after first in string

What I am trying to do is to remove duplicates of a specific given char in a string but letting the first char to remain. I.e:
let myStr = "hi. my .name."
//a function that gets a string and the element to be removed in the string
someFunc myStr "."
where someFunc returns the string showen as below:
"hi. my name"
It is easy to remove duplicates from a string, but is there a way to remove the duplicates but letting the first duplicated element remain in the string?
Here's one approach:
let keepFirst c s =
Seq.mapFold (fun k c' -> (c', k||c<>c'), k&&c<>c') true s
|> fst
|> Seq.filter snd
|> Seq.map fst
|> Array.ofSeq
|> System.String
let example = keepFirst '.' "hi. my .name."
let someFunc (str : string) c =
let parts = str.Split([| c |])
if Array.length parts > 1 then
seq {
yield Array.head parts
yield string c
yield! Array.tail parts
}
|> String.concat ""
else
str
Note that the character is given as char instead of a string.
let someFunc chr (str:string) =
let rec loop (a: char list) b = function
| [] -> a |> List.rev |> System.String.Concat
| h::t when h = chr -> if b then loop a b t
else loop (h::a) true t
| h::t -> loop (h::a) b t
loop [] false (str.ToCharArray() |> Array.toList)
Note that the character is given as char instead of a string.
Edit: Another way would be using regular expressions
open System.Text.RegularExpressions
let someOtherFunc c s =
let pat = Regex.Escape(c)
Regex.Replace(s, sprintf "(?<=%s.*)%s" pat pat, "")
Note that, in this case the character is given as string.
Edit 2:
let oneMoreFunc (c:char) (s:string) =
let pred = (<>) c
[ s |> Seq.takeWhile pred
seq [c]
s |> Seq.skipWhile pred |> Seq.filter pred ]
|> Seq.concat
|> System.String.Concat
When devising a function, think about gains from making its arguments generic. To pass state through the iteration, barring mutable variables, Seq.scan could be a weapon of choice. It folds into a tuple of new state and an option, then Seq.choose strips out the state and the unwanted elements.
In terms of functional building blocks, make it accept a predicate function 'a -> bool and let it return a function seq<'a> -> seq<'a>.
let filterDuplicates predicate =
Seq.scan (fun (flag, _) x ->
let p = predicate x in flag || p,
if flag && p then None else Some x ) (false, None)
>> Seq.choose snd
This can then easily reused to do other things as well, like 0 together with odd numbers.
filterDuplicates (fun i -> i % 2 = 0) [0..10]
// val it : seq<int> = seq [0; 1; 3; 5; ...]
Supplied with a call to the equality operator and fed into the constructor of System.String, you'll get near the signature you want, char -> seq<char> -> System.String.
let filterDuplicatesOfChar what s =
System.String(Array.ofSeq <| filterDuplicates ((=) what) s)
filterDuplicatesOfChar '.' "hi. my .name."
// val it : string = "hi. my name"

Haskell expand function

I was recently handed an assignment I have almost completed and I am currently in need of some help.
The first functions I needed to implement were lookUp, split, combine and keyWordDefs.
I then had to implement a function expand :: FileContents -> FileContents -> FileContents that takes the contents of a text file and an info file and combines them using the above functions to build a string representing the output file.
Here is my code so far:
module MP where
import System.Environment
type FileContents = String
type Keyword = String
type KeywordValue = String
type KeywordDefs = [(Keyword, KeywordValue)]
separators :: String
separators
= " \n\t.,:;!\"\'()<>/\\"
lookUp :: String -> [(String, a)] -> [a]
-- Given a search string and a list of string/item pairs, returns
-- the list of items whose associated string matches the search string.
lookUp x y = [a|(b,a) <- y, x==b]
split :: String -> String -> (String, [String])
-- Breaks up a string.
split as [] = ("",[""])
split as (b:bs)
| elem b as = (b:xs,"":y:ys)
| otherwise = (xs, (b:y):ys)
where
(xs,y:ys) = split as bs
combine :: [Char] -> [String] -> [String]
-- Combines the components of a string from its constituent separator
-- characters and words, as generated by a call to split.
combine [] y = y
combine (x:xs)(y:ys) = y : [x] : combine xs ys
getKeywordDefs :: [String] -> KeywordDefs
-- Takes the contents of an information file in the form of a list
-- of lines and which returns a list of keyword/definition pairs.
getKeywordDefs [] = []
getKeywordDefs (x:xs) = (keyword, concat defs) : getKeywordDefs xs
where
(_, (keyword : def)) = split " " x
defs = combine spaces def
spaces = [ ' ' | s <- [2..length def]]
expand :: FileContents -> FileContents -> FileContents
An example of the function expand is this:
expand "The capital of $1 is $2" "$1 Peru\n$2 Lima."
"The capital of Peru is Lima."
I suppose that this is going to work by 1st looking up (with function lookUp) if there is a "$" in the input string, then split the words, then replacing words that begin with "$" with the second input string, then combining them again all together? I am really confused actually, and I would like to know if anyone here understand how function expand will work.
Any help is welcome :)
Your expand function should look something like this:
-- It's probably better to change the type signature a little bit
-- because we're not returning the contents of a file, we're returning a string.
expand :: FileContents -> FileContents -> String
expand fc1 fc2 = let
keywordDefs = getKeywordDefs fc2
in replaceSymbols fc1 keywordDefs
Then you need a function named replaceSymbols, which splits up fc1 whenever it sees a $X, and then substitutes that $X for the result of looking up $X in keywordDefs.
replaceSymbols :: FileContents -> KeywordDefs -> String
Have a go at implementing that function and reply to this answer if you still need help :).

How can I make a function that takes a function as an argument and returns a modified version of that function?

Basically I need to create a function in Haskell which takes a function as an argument and returns another function with all the same pattern matching but with one extra pattern to match against. I'm not sure how possible this is and I couldn't find anything on google, but that might be because the title is as concise as I could think how to phrase this problem!
For example, say I had a function defined like this:
example :: String -> Integer
example "a" = 1
example "b" = 2
example _ = 0
and then another function with type:
example2 :: String -> Integer -> (String -> Integer) -> (String -> Integer)
example2 str int f = ?
how could I write the second function so that it would return a function which did exactly the same as the first function, except also return the Integer int when passed the String str?
example2 :: String -> Integer -> (String -> Integer) -> (String -> Integer)
example2 s x f = \a -> if a == s then x else f a
Note that this overrides any matching of s by f, i.e. example2 "c" 3 example is equivalent to:
f :: String -> Integer
f "c" = 3
f "a" = 1
f "b" = 2
f _ = 0

How To Change List of Chars To String?

In F# I want to transform a list of chars into a string. Consider the following code:
let lChars = ['a';'b';'c']
If I simply do lChars.ToString, I get "['a';'b';'c']". I'm trying to get "abc". I realize I could probably do a List.reduce to get the effect I'm looking for but it seems like there should be some primitive built into the library to do this.
To give a little context to this, I'm doing some manipulation on individual characters in a string and when I'm done, I want to display the resulting string.
I've tried googling this and no joy that way. Do I need to just bite the bullet and build a List.reduce expression to do this transformation or is there some more elegant way to do this?
Have you tried
System.String.Concat(Array.ofList(lChars))
How many ways can you build a string in F#?
Here's another handful:
let chars = ['H';'e';'l';'l';'o';',';' ';'w';'o';'r';'l';'d';'!']
//Using an array builder
let hw1 = new string [|for c in chars -> c|]
//StringBuilder-Lisp-like approach
open System.Text
let hw2 =
string (List.fold (fun (sb:StringBuilder) (c:char) -> sb.Append(c))
(new StringBuilder())
chars)
//Continuation passing style
let hw3 =
let rec aux L k =
match L with
| [] -> k ""
| h::t -> aux t (fun rest -> k (string h + rest) )
aux chars id
Edit: timings may be interesting? I turned hw1..3 into functions and fed them a list of 500000 random characters:
hw1: 51ms
hw2: 16ms
hw3: er... long enough to grow a beard? I think it just ate all of my memory.
Didn't see this one here, so:
let stringFromCharList (cl : char list) =
String.concat "" <| List.map string cl
"" is just an empty string.
FSI output:
> stringFromCharList ['a'..'d'];;
val it : string = "abcd"
EDIT:
Didn't like this syntax coming back to this so here's a more canonically functional one:
['a'..'z'] |> List.map string |> List.reduce (+)
['a';'b';'c'] |> List.fold_left (fun acc c -> acc ^ (string c)) ""
Edited:
Here is yet another funny way to do your task:
type t =
| N
| S of string
static member Zero
with get() = N
static member (+) (a: t, b: t) =
match a,b with
| S a, S b -> S (a+b)
| N, _ -> b
| _, N -> a
let string_of_t = function
|N -> ""
|S s -> s
let t_of_char c = S (string c)
['a'; 'b'; 'c'] |> List.map t_of_char |> List.sum |> string_of_t
Sadly, just extending System.String with 'Zero' member does not allow to use List.sum with strings.
Edited (answer to Juilet):
Yes, you are right, left fold is slow. But i know more slow right fold :) :
#r "FSharp.PowerPack"
List.fold_right (String.make 1 >> (^)) ['a';'b';'c'] ""
and of course there is fast and simple:
new System.String(List.to_array ['1';'2';'3'])
And i used 'sprintf' seems to me easier:
let t = "Not what you might expect"
let r = [ for i in "aeiou" -> i]
let q = [for a in t do if not (List.exists (fun x -> x=a) r) then yield a]
let rec m = function [] -> "" | h::t -> (sprintf "%c" h) + (m t)
printfn "%A" (m q)
The following solution works for me:
let charList = ["H";"E";"L";"L";"O"]
let rec buildString list =
match list with
| [] -> ""
| head::tail -> head + (buildString tail)
let resultBuildString = buildString charList
[|'w'; 'i'; 'l'; 'l'|]
|> Array.map string
|> Array.reduce (+)
or as someone else posted:
System.String.Concat([|'w'; 'i'; 'l'; 'l'|])

Resources