Defining types in SML? - string

If I want to check if a string starts with a letter and the rest of the characters can either be a letter or number, how would I define a datatype that is defined by those conditions? Or would pattern matching be the better route and if so, how would I check that?

If you don't care that using String.explode is a bit inefficient, then you can just define this predicate:
fun isName s = List.all Char.isAlpha (String.explode s)
Otherwise, you'd implement it via recursion over (the length of) the string itself.

Related

Is it possible to pattern match arguments in a function in haskell? [duplicate]

This question already has answers here:
Pattern matching identical values
(4 answers)
Closed 10 months ago.
I want the function isValid to return True if the first and second arguments match desPlanet and currPlanet from the 3rd argument. Is there a way I can do this?
Please see -
Not like that.
Patterns can only consist of 3 things:
A constructor, applied to as many sub-patterns as the constructor has arguments. Examples are Nothing, Just (Just x), or [desPlanet, _, currPlanet]:_, etc. The pattern will match values that were constructed with the same constructor, if all of the sub-patterns match the corresponding arguments in the value.
A variable, which will simply match anything and make the matched value available under that variable name. (The variable _ is a special, since it doesn't actually make the matched value available, and can thus be used multiple times across the pattern)
A literal like 123, "foo", 'c', etc; which will be matched by equality checking. (If the literal is polymorphic, like numeric literals with the Num class, then you may need an Eq constraint)
Note that there is no option to match anything against an existing variable (or against one bound elsewhere in the same pattern). The template you're trying to check against must be statically known, it can't be referred to by a variable. You either match against a specific concrete literal, or you match against a specific concrete constructor, or you just accept anything and bind it to a variable name.
However guards do allow you to check arbitrary conditions, and if the guard condition fails then the function will fall through to its next equation (just as if a pattern failed to match). So you can still do exactly what you want ("I want the function isValid to return True if the first and second arguments match desPlanet and currPlanet from the 3rd argument"); you just don't do solely with pattern matching.
For example:
isValid currPlanet desPlanet ([desPlanet', _, curPlanet'] : _) solarSys
| curPlanet == curPlanet' && desPlanet = desPlanet'
= True
isValid ... -- other equations

How to construct an array with multiple possible lengths using immutability and functional programming practices?

We're in the process of converting our imperative brains to a mostly-functional paradigm. This function is giving me trouble. I want to construct an array that EITHER contains two pairs or three pairs, depending on a condition (whether refreshToken is null). How can I do this cleanly using a FP paradigm? Of course with imperative code and mutation, I would just conditionally .push() the extra value onto the end which looks quite clean.
Is this an example of the "local mutation is ok" FP caveat?
(We're using ReadonlyArray in TypeScript to enforce immutability, which makes this somewhat more ugly.)
const itemsToSet = [
[JWT_KEY, jwt],
[JWT_EXPIRES_KEY, tokenExpireDate.toString()],
[REFRESH_TOKEN_KEY, refreshToken /*could be null*/]]
.filter(item => item[1] != null) as ReadonlyArray<ReadonlyArray<string>>;
AsyncStorage.multiSet(itemsToSet.map(roArray => [...roArray]));
What's wrong with itemsToSet as given in the OP? It looks functional to me, but it may be because of my lack of knowledge of TypeScript.
In Haskell, there's no null, but if we use Maybe for the second element, I think that itemsToSet could be translated to this:
itemsToSet :: [(String, String)]
itemsToSet = foldr folder [] values
where
values = [
(jwt_key, jwt),
(jwt_expires_key, tokenExpireDate),
(refresh_token_key, refreshToken)]
folder (key, Just value) acc = (key, value) : acc
folder _ acc = acc
Here, jwt, tokenExpireDate, and refreshToken are all of the type Maybe String.
itemsToSet performs a right fold over values, pattern-matching the Maye String elements against Just and (implicitly) Nothing. If it's a Just value, it cons the (key, value) pair to the accumulator acc. If not, folder just returns acc.
foldr traverses the values list from right to left, building up the accumulator as it visits each element. The initial accumulator value is the empty list [].
You don't need 'local mutation' in functional programming. In general, you can refactor from 'local mutation' to proper functional style by using recursion and introducing an accumulator value.
While foldr is a built-in function, you could implement it yourself using recursion.
In Haskell, I'd just create an array with three elements and, depending on the condition, pass it on either as-is or pass on just a slice of two elements. Thanks to laziness, no computation effort will be spent on the third element unless it's actually needed. In TypeScript, you probably will get the cost of computing the third element even if it's not needed, but perhaps that doesn't matter.
Alternatively, if you don't need the structure to be an actual array (for String elements, performance probably isn't that critical, and the O (n) direct-access cost isn't an issue if the length is limited to three elements), I'd use a singly-linked list instead. Create the list with two elements and, depending on the condition, append the third. This does not require any mutation: the 3-element list simply contains the unchanged 2-element list as a substructure.
Based on the description, I don't think arrays are the best solution simply because you know ahead of time that they contain either 2 values or 3 values depending on some condition. As such, I would model the problem as follows:
type alias Pair = (String, String)
type TokenState
= WithoutRefresh (Pair, Pair)
| WithRefresh (Pair, Pair, Pair)
itemsToTokenState: String -> Date -> Maybe String -> TokenState
itemsToTokenState jwtKey jwtExpiry maybeRefreshToken =
case maybeRefreshToken of
Some refreshToken ->
WithRefresh (("JWT_KEY", jwtKey), ("JWT_EXPIRES_KEY", toString jwtExpiry), ("REFRESH_TOKEN_KEY", refreshToken))
None ->
WithoutRefresh (("JWT_KEY", jwtKey), ("JWT_EXPIRES_KEY", toString jwtExpiry))
This way you are leveraging the type system more effectively, and could be improved on further by doing something more ergonomic than returning tuples.

lua_isstring() check for real strings in Lua

int lua_isstring (lua_State *L, int index);
This function returns 1 if the value at the given acceptable index is
a string or a number (which is always convertible to a string), and 0
otherwise. (Source)
Is there a (more elegant) way to really proof if the given string really is a string and not a number in Lua? This function makes absolutely no sense to me!
My first idea is to additionally examine the string-length with
`if(string.len(String) > 1) {/* this must be a string */}`
... but that does not feel so good.
You can replace
lua_isstring(L, i)
which returns true for either a string or a number by
lua_type(L, i) == LUA_TSTRING
which yields true only for an actual string.
Similarly,
lua_isnumber(L, i)
returns true either for a number or for a string that can be converted to a number; if you want more strict checking, you can replace this with
lua_type(L, i) == LUA_TNUMBER
(I've written wrapper functions, lua_isstring_strict() and lua_isnumber_strict().)
This function makes absolutely no sense to me!
It makes sense in light of Lua's coercion rules. Any function that accepts a string should also accept a number, converting that number to a string. That's just how the language semantics are defined. The way lua_isstring and lua_tostring work allow you automatically implement those semantics in your C bindings with no additional effort.
If you don't like those semantics and want to disable automation conversion between string and number, you can define LUA_NOCVTS2N and/or LUA_NOCVTN2S in your build. In particular, if you define LUA_NOCVTN2S, lua_isstring will return false for numbers.

Erlang: Matching strings in guard statement

Started working with erlang quite recently and ran into the problem above, how do you go about comparing two strings in a guard statement? Tried the string:equal(x,y) method but couldn't get it to work inside a guard.
You could use pattern matching like this:
are_the_same(A, A) ->
true;
are_the_same(_, _) ->
false.
In first clause both arguments are named A which will result in them being pattern matched against each other. Or to be exact first argument will be bind to A variable with use of = operator, and than second argument will be bind to A variable with = operator, but since A is bound already it will be treated as "comparision". You can read more about this in docs.
And of course you could write write first clouse with use of guard like:
are_the_same(A, B) when A =:= B ->
You don't need the function string:equal/2 to compare strings; you can use the operators == or =:=, which are allowed in guard tests. For example:
foo(A, B) when A =:= B ->
equal;
foo(_, _) ->
not_equal.
Though in most cases you'd want to use pattern matching instead, as described in the other answer.
NB: As of Erlang/OTP 20.0, string:equal(A, B) is no longer equivalent to A =:= B. string:equal/2 now operates on grapheme clusters, and there are also string:equal/3 and string:equal/4 that can optionally ignore case when comparing and do Unicode normalisation. So you need to understand what you mean by "equal" before settling on a comparison method.
The functions you can use in guards are limited because of the nature of Erlang's scheduling; specifically, Erlang aims to avoid side-effects in guard statements (e.g., calling to another process) because guards are evaluated by the scheduler and do not count against reductions. This is why string:equal does not work.
That being said, you can use Erlang's pattern matching to match strings. Please bear in mind the use of strings as lists, binaries, or iolists (nested lists/binaries) in Erlang, and make sure you're testing/passing strings of the right type (iolists are particularly hard to pattern match and are usually best handled with the re module, or converting them to binaries via iolist_to_binary).
For example, say we want a function that tests to see if a string begins with "foo":
bar("foo" ++ _Rest) -> true;
bar(<<"foo", Rest/binary>>) -> true;
bar(_Else) -> false.
If you just want to test for a particular string, it's even easier:
bar("foo") -> true;
bar(<<"foo">>) -> true;
bar(_Else) -> false.

Update2,Haskell

Atom: The Atom is the datatype used to describe Atomic Sentences or propositions. These are basically
represented as a string.
Literal: Literals correspond to either atoms or negations of atoms. In this implementation each literal
is represented as a pair consisting of a boolean value, indicating the polarity of the Atom, and the
actual Atom. Thus, the literal ā€˜Pā€™ is represented as (True,"P") whereas its negation ā€˜-Pā€™ as
(False,"P").
2
Clause: A Clause is a disjunction of literals, for example PvQvRv-S. In this implementation this
is represented as a list of Literals. So the last clause would be [(True,"P"), (True,"Q"),
(True,"R"),(False,"S")].
Formula: A Formula is a conjunction of clauses, for example (P vQ)^(RvP v-Q)^(-P v-R).
This is the CNF form of a propositional formula. In this implementation this is represented as a list of
Clauses, so it is a list of lists of Literals. Our above example formula would be [[(True,"P"),
(True,"Q")], [(True,"R"), (True,"P"), (False,"Q")], [(False, "P"),
(False,"P")]].
Model: A (partial) Model is a (partial) assignment of truth values to the Atoms in a Formula. In this
implementation this is a list of (Atom, Bool) pairs, ie. the Atoms with their assignments. So in the
above example of type Formula if we assigned true to P and false to Q then our model would be
[("P", True),("Q", False)]
Ok so I wrote and update function
update :: Node -> [Node]
It takes in a Node and returns a list of the Nodes
that result from assigning True to an unassigned atom in one case and False in the other (ie. a case
split). The list returned has two nodes as elements. One node contains the formula
with an atom assigned True and the model updated with this assignment, and the other contains
the formula with the atom assigned False and the model updated to show this. The lists of unassigned
atoms of each node are also updated accordingly. This function makes use of an
assign function to make the assignments. It also uses the chooseAtom function to
select the literal to assign.
update :: Node -> [Node]
update (formula, (atoms, model)) = [(assign (chooseAtom atoms, True) formula, (remove (chooseAtom atoms) atoms, ((chooseAtom atoms,True)) `insert` model)) , (assign (chooseAtom atoms, False) formula, (remove (chooseAtom atoms) atoms, ((chooseAtom atoms, False) `insert` model)) )]
Now I have to do the same thing but this time I must implement a variable selection heuristic.this should replace the chooseAtom and I'm supposed to write a function update2 using it
type Atom = String
type Literal = (Bool,Atom)
type Clause = [Literal]
type Formula = [Clause]
type Model = [(Atom, Bool)]
type Node = (Formula, ([Atom], Model))
update2 :: Node -> [Node]
update2 = undefined
So my question is how can I create a heurestic and to implement it into the update2 function ,that shoud behave identical to the update function ?
If I understand the question correctly, you're asking how to implement additional selection rules in resolution systems for propositional logic. Presumably, you're constructing a tree of formulas gotten by assigning truth-values to literals until either (a) all possible combinations of assignments to literals have been tried or (b) box (the empty clause) has been derived.
Assuming the function chooseAtom implements a selection rule, you can parameterize the function update over an arbitrary selection rule r by giving update an additional parameter and replacing the occurrence of chooseAtom in update by r. Since chooseAtom implements a selection rule, passing that selection rule to the parameter r gives the desired result. If you provide an implementation of chooseAtom and the function you intend to replace it, it would be easier to verify that your implementation is correct.
Hopefully this is helpful. However, it's unclear exactly what's being asked. In particular, you're asking for a "variable selection rule." However, it looks like you're implementing a resolution system for propositional logic. In general, selection rules and variables are associated with resolution for predicate logic.

Resources