Map list of text to their letter-counts in unison - unison-lang

I wonder why
use .base
use .List
> foo = ["abc", "abcdef", "a", "zzz"]
> map (x -> size x) foo
The last row errors. Ucm says:
I'm not sure what size means at line 5, columns 13-17
5 | > map (x -> size x) foo
Whatever it is, it has a type that conforms to a ->{𝕖} b.
I found some terms in scope that have matching names and types. Maybe you meant one of these:
- .base.Bytes.size : base.Bytes -> base.Nat
- .base.Heap.size : base.Heap k v -> base.Nat
- .base.List.Nonempty.size : base.List.Nonempty a -> base.Nat
- .base.List.size : [a] -> base.Nat
- .base.Map.size : base.Map k v -> base.Nat
- .base.Set.size : base.Set k -> base.Nat
- .base.Text.size : base.Text -> base.Nat
It's the bottom one I'm aiming for in the mapping function.
I've tried:
> map (x -> size "foobar") foo
> size "johndoe"
And both of those give me what I would expect.

Unison is confused somehow and you need to qualify which size-function you want by doing:
map (x -> Text.size x) b

Related

The difference between dependent type signatures and proofs

With dependent types, you can either capture function properties in the type signature, like in concatenation with length-indexed lists
(++) : Vect m a -> Vect n a -> Vect (m + n) a
or you can not use dependent types in your signature, like concatenation with standard lists
(++) : List a -> List a -> List a
and write proofs about (++)
appendAddsLength : (xs, ys : List a) -> length (xs ++ ys) = length xs + length ys
lengthNil : length [] = 0
lengthCons : (x : a) -> (xs : List a) -> length (x :: xs) = length xs + 1
Is there any difference between these approaches beyond ergonomics?
The most obvious difference is that, with (++) on Vects, the length is statically known: you can operate on it at compile time. Moreover, you don't need to write any additional proofs in order to ensure that (++) has the expected behavior on Vects, whereas you need to do it for Lists.
That is, (++) on Vect is correct by construction. The compiler will always enforce the desired properties, whether you like it or not, and without the user taking any additional action.
It's important to note that length xs is not really interchangeable with the statically-known size in general. On these data types, length is a function which actually re-computes the length of a List or Vect by walking through it and incrementing a counter:
libs/prelude/Prelude/Types.idr:L403-L407
namespace List
||| Returns the length of the list.
public export
length : List a -> Nat
length [] = Z
length (x :: xs) = S (length xs)
libs/base/Data/Vect.idr:25-28
public export
length : (xs : Vect len elem) -> Nat
length [] = 0
length (_::xs) = 1 + length xs
Even with Vect, the length built into to the type by construction, but the result of applying the length function to a List or Vect is not fundamental at all. In fact, Data.Vect contains a proof that Data.Vect.length that applying length to a Vect n t always returns n:
libs/base/Data/Vect.idr:30-34
||| Show that the length function on vectors in fact calculates the length
export
lengthCorrect : (xs : Vect len elem) -> length xs = len
lengthCorrect [] = Refl
lengthCorrect (_ :: xs) = rewrite lengthCorrect xs in Refl
Using the above proof, we can assert statically, without actually executing length, that the result of length is propositionally equal to the statically-known length of the Vect. But this assurance is not available for List. And it's much more cumbersome to work with in general, likely requiring the use of with ... proof and rewrite a lot more than just using the correct-by-construction type.

definition of a type doesn’t work in agda

This definition of modular arithmetic doesn’t compile in agda :
data mod (n : nat): n → Set where
zeroM : mod n
S : mod n → mod n
equMod : { x : nat} → (x ≡ n) → (x ≡ zeroM)
Error: nat should be a sort, but isn’t
Can someone help me ?
When you write n -> Set you need n to be a type but it is a natural number. I guess you just want to write data mod (n : nat) : Set which means that mod : nat -> Set.

Is there a specific type for mathematical functions in Haskell?

I want to write a function that takes a mathematical function (/,x,+,-), a number to start with and a list of numbers. Then, it's supposed to give back a list.
The first element is the starting number, the second element the value of the starting number plus/minus/times/divided by the first number of the given list. The third element is the result of the previous result plus/minus/times/divided by the second result of the given list, and so on.
I've gotten everything to work if I tell the code which function to use but if I want to let the user input the mathematical function he wants, there are problems with the types. Trying :t (/) for example gives out Fractional a => a -> a -> a, but if you put that at the start of your types, it fails.
Is there a specific type to distinguish these functions (/,x,+,-)? Or is there another way to write this function succesfully?
prefix :: (Fractional a, Num a) => a -> a -> a -> a -> [a] -> [a]
prefix (f) a b = [a] ++ prefix' (f) a b
prefix' :: (Fractional a, Num a) => a -> a -> a -> a -> [a] -> [a]
prefix' (z) x [] = []
prefix' (z) x y = [x z (head y)] ++ prefix' (z) (head (prefix' (z) x y)) (tail y)
A right solution would be something like this:
prefix (-) 0 [1..5]
[0,-1,-3,-6,-10,-15]
Is there a specific type to distinguish these functions (/,*,+,-)?
I don't see a reason to do this. Why is \x y -> x+y considered "better" than \x y -> x + y + 1. Sure adding two numbers is something that most will consider more "pure". But it is strange to restrict yourself to a specific subset of functions. It is also possible that for some function \x y -> f x y - 1 "happens" to be equal to (+), except that the compiler can not determine that.
The type checking will make sure that one can not pass functions that operate on numbers, given the list contains strings, etc. But deliberately restricting this further is not very useful. Why would you prevent programmers to use your function for different purposes?
Or is there another way to write this function succesfully?
What you here describe is the scanl :: (b -> a -> b) -> b -> [a] -> [b] function. If we call scanl with scanl f z [x1, x2, ..., xn], then we obtain a list [z, f z x1, f (f z x1) x2, ...]. scanl can be defined as:
scanl :: (b -> a -> b) -> b -> [a] -> [b]
scanl f = go
where go z [] = [z]
go z (x:xs) = z : go (f z x) xs
We thus first emit the accumulator (that starts with the initial value), and then "update" the accumulator to f z x with z the old accumulator, and x the head of the list, and recurse on the tail of the list.
If you want to restrict to these four operations, just define the type yourself:
data ArithOp = Plus | Minus | Times | Div
as_fun Plus = (+)
as_fun Minus = (-)
as_fun Times = (*)
as_fun Div = (/)

What is wrong with this Haskell list code?

Here is an example of what I wanted to do.
let b = ["this","is","a","test!"]
"xx" ++ (b!!3)
This will give me "xxtest!"
Basically if the list contains any string with an exclamation mark then "xx" will be added to this specific string. My questions is how to implement this into a correct function.
Currently I got this
replaceElement [] = []
replaceElement (x:xs) =
if '!' `elem` x
then ["xx"] ++ x : replaceElement xs
else x: replaceElement xs
But this function will just add "xx" into list as an element, it won't be added to the specific string in the list. How can I use "xx" ++ (b!!x) where x is the position of the string with an exclamation mark.
The expression
["xx"] ++ x : replaceElement xs
is actually parsed as
["xx"] ++ (x : replaceElement xs)
which does just what you described: inserts "xx" into the resulting list. What you want to do instead, is:
("xx" ++ x) : replaceElement xs
The crucial thing is how ["xx"] ++ x : replaceElement xs is parsed. This is determined by the fixities of the operators:
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :info :
-- ...
infixr 5 :
Prelude> :i ++
(++) :: [a] -> [a] -> [a] -- Defined in ‘GHC.Base’
infixr 5 ++
So, both : and ++ are right-associative operators, with the same precedence. Right-associative means, a : b : c is parsed as a : (b : c), instead of (a : b) : c (as would be the case for left-associative infixl). Due to the equal precedence, this still holds if you mix : and ++, i.s.
["xx"] ++ x : replaceElement xs ≡ ["xx"] ++ (x : replaceElement xs)
IOW, you're just prepending ["xx"] to the whole result, but the individual elements never get in contact with "xx". To achieve that, you need to group "xx" with x. The extra brackets are unnecessary then (in fact these could have tipped you off: wrapping "xs" in an extra layer means you're not working of the string-level anymore as intended, but on the list-of-string level).
A better alternative would of course be to not do any manual recursion: you're simply applying the same operation to all elements of a list; that's what map is there for:
replaceElement = map $ \x -> if '!'`elem`x
then "xx"++x
else x
You may also use map with a helper function like;
addxx :: [String] -> [String]
addxx = map checkBang
where checkBang s | last s == '!' = "xx" ++ s
| otherwise = s

F# generics / function overloading syntax

I'm confused on how to label a function as generic without an explicit type declaration like ('a -> 'a)
let add a b = a + b
This gives us
val add : a:int -> b:int -> int
However we can then immediately call
add "Hello " "World!"
and now the value of add is
val add : a:string -> b:string -> string
val it : string = "Hello World!"
If we then call
add 2 3 // then we get
error: This expression was expected to have type string but here has type int
How do I ensure that a function works on all types that say have the function (+) defined
This is F#'s embarrassing skeleton in the closet.
Try this:
> let mapPair f (x,y) = (f x, f y)
val mapPair : f:('a -> 'b) -> x:'a * y:'a -> 'b * 'b
Fully generic! Clearly, function application and tuples work.
Now try this:
> let makeList a b = [a;b]
val makeList : a:'a -> b:'a -> 'a list
Hmmm, also generic. How about this:
> let makeList a b = [a + b]
val makeList : a:int -> b:int -> int list
Aha, as soon as I have a (+) in there, it becomes int for some reason.
Let's keep playing:
> let inline makeList a b = [a + b]
val inline makeList :
a: ^a -> b: ^b -> ^c list
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
Hmmm, interesting. Turns out, if I make the function inline, then F# does consider it generic, but it also gives it this weird when clause, and my generic parameters have this strange ^ symbol instead of the usual tick.
This strange syntax is called "statically resolved type parameters" (see here for a somewhat coherent explanation), and the basic idea is that the function (+) requires its arguments to have a static member (+) defined. Let's verify:
> let x = 0 :> obj
let y = 0 :> obj
let z = x + y
Script1.fsx(14,13): error FS0001: The type 'obj' does not support the operator '+'
> type My() =
static member (+)( a:My, b:My ) = My()
let x = My()
let y = My()
let z = x + y
val x : My
val y : My
val z : My
Now, the problem with this is that CLR does not support this kind of generic parameters (i.e. "any type, as long as it has such and such members"), so F# has to fake it and resolve these calls at compile time. But because of this, any methods that use this feature cannot be compiled to true generic IL methods, and thus have to be monomorphised (which is enabled by inline).
But then, it would be very inconvenient to require that every function that uses arithmetic operators be declared inline, wouldn't it? So F# goes yet another extra step and tries to fix these statically resolved generic parameters based on how they are instantiated later in the code. That's why your function turns into string->string->string as soon as you use it with a string once.
But if you mark your function inline, F# wouldn't have to fix parameters, because it wouldn't have to compile the function down to IL, and so your parameters remain intact:
> let inline add a b = a + b
val inline add :
a: ^a -> b: ^b -> ^c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
If I understand you correctly, use inline:
let inline add a b = a + b
add 2 3 |> printfn "%A"
add "Hello " "World!" |> printfn "%A"
Print:
5
"Hello World!"
Link: http://ideone.com/awsYNI
Make it inline
let inline add a b = a + b
(*
val inline add :
a: ^a -> b: ^b -> ^c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
*)
add "Hello " "World!"
// val it : string = "Hello World!"
add 2 3
// val it : int = 5