Considering the following agda module signature:
module EqList {a ℓ} {A : Set a} {_≈_ : Rel A ℓ} (eq≈ : IsEquivalence _≈_) where
We can define the membership in a list, the list inclusion and the list equivalence:
_∈_ : REL A (List A) _
_∈_ x = Any (x ≈_)
_⊑_ : Rel (List A) _
_⊑_ = _⊆_ on flip _∈_
_≋_ : Rel (List A) _
_≋_ = _⊑_ -[ _×_ ]- flip _⊑_
We can then proceed to prove that this last relation is indeed an equivalence relation:
isEq≋ : IsEquivalence _≋_
isEq≋ = record {
refl = id , id ;
sym = swap ;
trans = zip (λ f g → g ∘ f) λ f g → f ∘ g }
The proof of transitivity is what makes my question arise. The previous definition is accepted by Agda while the following is rejected:
trans = zip (flip _∘_) _∘_
The error is as follows:
({x : A} → Any (_≈_ x) i → Any (_≈_ x) j) !=
((x : A) → Any (_≈_ x) j) because one is an implicit function type
and the other is an explicit function type
when checking that the expression _∘_ has type
(x : j ⊑ k) (y : i ⊑ j) → i ⊑ k
While this error feels weird, because both proofs should be equivalent (replacing the expression f by the expression λ x → f x should always yield the same result) I can somewhat understand why it behaves this way : there is intern trouble as to how to instantiate the various implicit arguments of _∘_. But this explanation is only intuitive and not very conclusive, so my question is the following:
Can someone explain in details why the typechecker succeeds in the first case and not in the second ?
As a side note, here is the header of the module, in order for this example to be self contained:
open import Relation.Binary.Core
open import Data.List hiding (zip)
open import Data.List.Any
open import Relation.Unary using (_⊆_)
open import Function
open import Data.Product
As a second side note, I am aware that a similar question has already been answered:
How to get around the implicit vs explicit function type error?
But said answer does not contain any deep explanation about this surprising behavior.
Suppose we have a composite type:
mutable struct MyType{TF<:AbstractFloat, TI<:Integer}
a::TF
b::TF
end
We define a constructor
function MyType(a; b = 1.0)
return MyType(a, b)
end
I can broadcast MyType over an array of a's, but how can I do that for b's?
I tried to do
MyType.([1.0, 2.0, 3.0]; [:b, 1.0, :b, 2.0, :b, 3.0,])
But, this does not work.
Note that the above example is totally artificial. In reality, I have a composite type that takes in many fields, many of which are constructed using keyword arguments, and I only want to change a few of them into different values stored in an array.
I don't think you can do this with dot-notation, however, you can manually construct the broadcast call:
julia> struct Foo
a::Int
b::Int
Foo(a; b = 1) = new(a, b)
end
julia> broadcast((x, y) -> Foo(x, b = y), [1,2,3], [4,5,6])
3-element Array{Foo,1}:
Foo(1, 4)
Foo(2, 5)
Foo(3, 6)
julia> broadcast((x, y) -> Foo(x; y), [1,2,3], [:b=>4,:b=>5,:b=>6])
3-element Array{Foo,1}:
Foo(1, 4)
Foo(2, 5)
Foo(3, 6)
I'm just learning a haskell and seems like all is good even scary monads are not a big deal for me. But I can't get to real practiacal stuff at all.
My first practical task for haskell I choosed as follows:
Given a JSON describing some binary file's format to parse that file.
JSON has some deeply nested structure with lists of assocoative lists (dictionaries) of lists etc with endpoints as numbers or strings.
So first of all I want to be able to map other those endpoints (to have functor class for jsons data) converting some strings to numbers in particular. Also it would be nice to be able to fold all those endpoints as well.
I came up with some python code easily. But can't go any far with haskell.
So what your suggestions for implementing things in haskell? It really would be nice to hear some advise for solutions using libraries to greatest extent and not handwrite all the stuff from scratch.
Thanks in advance!
added---
example of what I have in python
Some helper functions:
islist = lambda l: isinstance(l, collections.Iterable) and not isinstance(l, (str, bytes))
isdict = lambda d: isinstance(d, collections.Mapping)
isiter = lambda i: islist(i) or isdict(i)
def iterable(d):
if isdict(d):
i = d.items()
elif islist(d):
i = enumerate(d)
else:
raise ValueError
return i
Iterator over nested json data:
def nested_iter(nested, f = lambda *args: None):
for key, value in iterable(nested):
if not isiter(value):
f(nested, key)
yield key, value
else:
yield from nested_iter(value, f)
now I can substitute some numbers with lists of keys:
def list_from_num(d, k):
if type(d[k]) == int:
d[k] = [k]*d[k]
list(nested_iter(typedef, list_from_num))
or I can substitute some strings with some other nested data with the same key name
def nest_dicts(defs, d, k):
if d[k] in defs.keys():
d[k] = deepcopy(defs[d[k]])
if isiter(d[k]):
list(nested_iter(d[k], partial(nest_dicts, defs)))
list(nested_iter(typedef, partial(nest_dicts, typedef)))
or can just flatten data
list(nested_iter(d))
parsing binary is a bit more evolved but it is nothing more as passing to iterator one more function
Well this is my solution.
It uses Control.Lens, Data.Aeson.Lens, Control.Lens.Plated
One can use transform from Uniplate or Lens.Plated to transform values.
for example to substitute each number with list of key values of length of that number:
n2k :: T.Text -> Value -> Value --import qualified Data.Text as T
n2k s (Number x)
| isInteger x = case toBoundedInteger x of
Just n -> Array (V.replicate n (String s)) -- import qualified Data.Vector as V
_ -> Number x
| otherwise = Number x
n2k _ v = v
f (Object o) = Object $ imap n2k o --imap from Data.Map.Lens
f x = x
j2 = transform f j --transform JSON j using function f
to substitute string with data with same key:
-- o is hashmap where we are looking for keys to substitute strings
h (String s) = fromMaybe (String s) (H.lookup s o) --import qualified Data.HashMap.Lazy as H
h x = x
j2 = transform h j
just get all numbers into list:
l = [x | Number x <- universe j]
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
Is it possible to remove the duplicates (as in nub) from a list of functions in Haskell?
Basically, is it possible to add an instance for (Eq (Integer -> Integer))
In ghci:
let fs = [(+2), (*2), (^2)]
let cs = concat $ map subsequences $ permutations fs
nub cs
<interactive>:31:1:
No instance for (Eq (Integer -> Integer))
arising from a use of `nub'
Possible fix:
add an instance declaration for (Eq (Integer -> Integer))
In the expression: nub cs
In an equation for `it': it = nub cs
Thanks in advance.
...
Further, based on larsmans' answer, I am now able to do this
> let fs = [AddTwo, Double, Square]
> let css = nub $ concat $ map subsequences $ permutations fs
in order to get this
> css
[[],[AddTwo],[Double],[AddTwo,Double],[Square],[AddTwo,Square],[Double,Square],[AddTwo,Double,Square],[Double,AddTwo],[Double,AddTwo,Square],[Square,Double],[Square,AddTwo],[Square,Double,AddTwo],[Double,Square,AddTwo],[Square,AddTwo,Double],[AddTwo,Square,Double]]
and then this
> map (\cs-> call <$> cs <*> [3,4]) css
[[],[5,6],[6,8],[5,6,6,8],[9,16],[5,6,9,16],[6,8,9,16],[5,6,6,8,9,16],[6,8,5,6],[6,8,5,6,9,16],[9,16,6,8],[9,16,5,6],[9,16,6,8,5,6],[6,8,9,16,5,6],[9,16,5,6,6,8],[5,6,9,16,6,8]]
, which was my original intent.
No, this is not possible. Functions cannot be compared for equality.
The reason for this is:
Pointer comparison makes very little sense for Haskell functions, since then the equality of id and \x -> id x would change based on whether the latter form is optimized into id.
Extensional comparison of functions is impossible, since it would require a positive solution to the halting problem (both functions having the same halting behavior is a necessary requirement for equality).
The workaround is to represent functions as data:
data Function = AddTwo | Double | Square deriving Eq
call AddTwo = (+2)
call Double = (*2)
call Square = (^2)
No, it's not possible to do this for Integer -> Integer functions.
However, it is possible if you're also ok with a more general type signature Num a => a -> a, as your example indicates! One naïve way (not safe), would go like
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
data NumResLog a = NRL { runNumRes :: a, runNumResLog :: String }
deriving (Eq, Show)
instance (Num a) => Num (NumResLog a) where
fromInteger n = NRL (fromInteger n) (show n)
NRL a alog + NRL b blog
= NRL (a+b) ( "("++alog++ ")+(" ++blog++")" )
NRL a alog * NRL b blog
= NRL (a*b) ( "("++alog++ ")*(" ++blog++")" )
...
instance (Num a) => Eq (NumResLog a -> NumResLog a) where
f == g = runNumResLog (f arg) == runNumResLog (g arg)
where arg = NRL 0 "THE ARGUMENT"
unlogNumFn :: (NumResLog a -> NumResLog c) -> (a->c)
unlogNumFn f = runNumRes . f . (`NRL`"")
which works basically by comparing a "normalised" version of the functions' source code. Of course this fails when you compare e.g. (+1) == (1+), which are equivalent numerically but yield "(THE ARGUMENT)+(1)" vs. "(1)+(THE ARGUMENT)" and thus are indicated as non-equal. However, since functions Num a => a->a are essentially constricted to be polynomials (yeah, abs and signum make it a bit more difficult, but it's still doable), you can find a data type that properly handles those equivalencies.
The stuff can be used like this:
> let fs = [(+2), (*2), (^2)]
> let cs = concat $ map subsequences $ permutations fs
> let ncs = map (map unlogNumFn) $ nub cs
> map (map ($ 1)) ncs
[[],[3],[2],[3,2],[1],[3,1],[2,1],[3,2,1],[2,3],[2,3,1],[1,2],[1,3],[1,2,3],[2,1,3],[1,3,2],[3,1,2]]