Elm Colon Equals Operator - elm

When attempting to decode larger json values, I've ran into the following code in the Json-Decode-Extra library. (located here)
import Date (Date)
type alias User =
{ id : Int
, createdAt : Date
, updatedAt : Date
, deletedAt : Maybe Date
, username : Maybe String
, email : Maybe String
, fullname : Maybe String
, avatar : Maybe String
, isModerator : Bool
, isOrganization : Bool
, isAdmin : Bool
}
metaDecoder : (Int -> Date -> Date -> Maybe Date -> b) -> Decoder b
metaDecoder f = f
`map` ("id" := int)
`apply` ("createdAt" := date)
`apply` ("updatedAt" := date)
`apply` ("deletedAt" := maybe date)
userDecoder : Decoder User
userDecoder = metaDecoder User
`apply` ("username" := maybe string)
`apply` ("email" := maybe string)
`apply` ("fullname" := maybe string)
`apply` ("avatar" := maybe string)
`apply` ("isModerator" := bool)
`apply` ("isOrganization" := bool)
`apply` ("isAdmin" := bool)
However, I'm constantly running into a compiler error for the := operator. Where is this defined? The JSON decode tutorials don't explicitly import this operator anywhere.

In Elm 0.18, the := operator was replaced by Json.Decode.field, and using backticks for infix operators was removed.
You are using a package (circuithub/elm-json-extra) which has not been updated to Elm 0.18.
Consider switching to use the package maintained by the Elm community: elm-community/json-extra. You can use andMap instead of apply. Here is your example code upgraded to the new library and Elm 0.18:
import Date exposing (Date)
import Json.Decode exposing (..)
import Json.Decode.Extra exposing (andMap, date)
metaDecoder : (Int -> Date -> Date -> Maybe Date -> b) -> Decoder b
metaDecoder f =
succeed f
|> andMap (field "id" int)
|> andMap (field "createdAt" date)
|> andMap (field "updatedAt" date)
|> andMap (field "deletedAt" (maybe date))
userDecoder : Decoder User
userDecoder =
metaDecoder User
|> andMap (field "username" (maybe string))
|> andMap (field "email" (maybe string))
|> andMap (field "fullname" (maybe string))
|> andMap (field "avatar" (maybe string))
|> andMap (field "isModerator" bool)
|> andMap (field "isOrganization" bool)
|> andMap (field "isAdmin" bool)
Note that the elm-community/json-extra package also exports an infix operator |: which is an infix version of andMap. You could use this to make your code more concise. For example:
metaDecoder : (Int -> Date -> Date -> Maybe Date -> b) -> Decoder b
metaDecoder f =
succeed f
|: field "id" int
|: field "createdAt" date
|: field "updatedAt" date
|: field "deletedAt" (maybe date)

Related

How to pass function through a custom Idris FFI?

I'm trying to implement the FFI part for my codegen, and although passing values like Int works, my biggest issue is figuring out how to pass a function.
So, in the docs there is this example with the JS FFI, that passes a function to the JS world, calls it there, and gets the result back, which is what I'm trying to implement. The code in the docs is this:
function twice(f, x) {
return f(f(x));
}
and the Idris code for the FFI binding is this one:
twice : (Int -> Int) -> Int -> IO Int
twice f x = mkForeign (
FFun "twice(%0,%1)" [FFunction FInt FInt, FInt] FInt
) f x
I don't have access to the mkForeign function, because it looks that is from the JS codegen RTS. So I tried to use foreign from Idris builtins:
twice : (Int -> Int) -> Int -> IO Int
twice =
foreign FFI_AHK "twice"
((Int -> Int) -> Int -> IO Int)
Which errors in:
When checking right hand side of twice with expected type
(Int -> Int) -> Int -> IO Int
When checking argument fty to function foreign:
Can't find a value of type
FTy FFI_AHK [] ((Int -> Int) -> Int -> IO Int)
Which I guess it is due to the last parameter of foreign , which has type
{auto fty : FTy f [] ty}
Documented as:
fty - an automatically-found proof that the Idris type works with the FFI in question
How does one satisfy this proof? I'm pretty lost at this point
The JavaScript FFI descriptor part of the docs was very useful in order to fix this.
What was needed was to provide an additional data type in order to wrap the functions so Idris can autogenerate the fty parameter of foreign.
The complete FFI definition of my code generator looks like this:
mutual
public export
data AutoHotkeyFn t = MkAutoHotkeyFn t
public export
data AHK_FnTypes : Type -> Type where
AHK_Fn : AHK_Types s -> AHK_FnTypes t -> AHK_FnTypes (s -> t)
AHK_FnIO : AHK_Types t -> AHK_FnTypes (IO' l t)
AHK_FnBase : AHK_Types t -> AHK_FnTypes t
public export
data AHK_Types : Type -> Type where
AHK_Str : AHK_Types String
AHK_Int : AHK_Types Int
AHK_Float : AHK_Types Double
AHK_Unit : AHK_Types ()
AHK_Raw : AHK_Types (Raw a)
AHK_FnT : AHK_FnTypes t -> AHK_Types (AutoHotkeyFn t)
public export
data AHK_Foreign
= AHK_DotAccess String String
| AHK_Function String
public export
FFI_AHK : FFI
FFI_AHK = MkFFI AHK_Types AHK_Foreign String
In order to write the twice function above, one can wrap the function type with AutoHotkeyFn and then do the same with the value of the function, by wrapping it in MkAutoHotkeyFn:
twice : (Int -> Int) -> Int -> AHK_IO Int
twice f x =
foreign FFI_AHK (AHK_Function "twice")
(AutoHotkeyFn (Int -> Int) -> Int -> AHK_IO Int)
(MkAutoHotkeyFn f)
x

Compilation error while implementing extensible record

I'm playing around with idris and was trying to implement extensible records.
The main goal is to guarantee that the record's keys are unique.
For example
("Year" := 1998) +: rnil
is legal
("Title" := "test") +: ("Year" := 1998) +: rnil
also works, but
("Year" := "test") +: ("Year" := 1998) +: rnil
Should fail to compile.
I came up with the following implementation which compiles fine:
{-
See: http://lpaste.net/104020
and https://github.com/gonzaw/extensible-records
-}
module Record
import Data.List
%default total
data HList : List Type -> Type where
Nil : HList []
(::) : a -> HList xs -> HList (a :: xs)
infix 5 :=
data Field : lbl -> Type -> Type where
(:=) : (label : lbl) ->
(value : b) -> Field label b
labelsOf : List (lbl, Type) -> List lbl
labelsOf [] = []
labelsOf ((label, _) :: xs) = label :: labelsOf xs
toFields : List (lbl, Type) -> List Type
toFields [] = []
toFields ((l, t) :: xs) = (Field l t) :: toFields xs
data IsSet : List t -> Type where
IsSetNil : IsSet []
IsSetCons : Not (Elem x xs) -> IsSet xs -> IsSet (x :: xs)
data Record : List (lty, Type) -> Type where
MkRecord : IsSet (labelsOf ts) -> HList (toFields ts) ->
Record ts
infixr 6 +:
rnil : Record []
rnil = MkRecord IsSetNil []
prepend : { label : lbl,
xs : List (lbl, Type),
prf : Not (Elem label (labelsOf xs))
} ->
Field label t ->
Record xs ->
Record ((label, t) :: xs)
prepend {prf} f (MkRecord isSet fs) = MkRecord (IsSetCons prf isSet) (f :: fs)
data IsNo : Dec prop -> Type where
ItIsNo : IsNo (No y)
(+:) : DecEq lbl =>
{ label : lbl, xs : List (lbl, Type) } ->
Field label t ->
Record xs ->
{ auto isno : IsNo (isElem label $ labelsOf xs) } ->
Record ((label, t) :: xs)
(+:) {label} {xs} f r with (isElem label $ labelsOf xs)
(+:) { isno = ItIsNo } _ _ | (Yes _) impossible
(+:) f r | (No no) = prepend {prf = no} f r
The interesting bit is
{ auto isno : IsNo (isElem label $ labelsOf xs) } ->
The idea is that if the keys are unique, the compiler will trivialy find an instance of IsNo while it won't if keys are not unique and therefore fail to compile.
This works well with for those example
("Year" := 1998) +: rnil -- Compiles fine
("Year" := "test") +: ("Year" := 1998) +: rnil -- fails to compile as expected
But
("Title" := "test") +: ("Year" := 1998) +: rnil
fails to compile with the following error:
(input):Type mismatch between
("Title" = "Year") -> "Title" = "Year"
and
("Title" = "Year") -> Void
I must admit that this error baffles me. Can anyone explain what's happening here ?
It seems that you're the first to use the DecEq instance for String in anger and as a result, you're the first to find that the way we build proof terms for primitives here is wrong. Sorry about that. The good news is that it's easy to fix (I've just tried it on your example and it's fine), the bad news is that you'll need the git head once I've pushed the fix.
We're overdue a new release anyway. I'll try to do that this weekend. Your code certainly looks fine to me!

Elm: How can I find out the type of an Elm expression or a subexpression in elm-repl?

How can I find out the type of an Elm expression or a subexpression in elm-repl ?
Haskell's :type or :t equivalent in Elm REPL?
The Elm REPL automatically prints the type of whatever you enter. For example:
> "foo"
"foo" : String
> f = \a b c -> (a + 1, b ++ "!", c || False)
<function> : number -> String -> Bool -> ( number, String, Bool )
> f
<function> : number -> String -> Bool -> ( number, String, Bool )
> f2 a b c = (a + 1, b ++ "!", c || False)
<function> : number -> String -> Bool -> ( number, String, Bool )
As #amalloy points out, without an equivalent to GHCi's :type command, Elm REPL (as of 0.18) forces evaluation of an expression prior to showing you the type, which may be undesirable for expensive function calls. In its current version, there is no way around this.

How do I build a HMAC code in Elm?

I'm trying to implement HMAC in Elm,
but I can't seem to figure out what I'm doing wrong here.
Some help would be greatly appreciated 🙏
type alias HashFunction =
String -> String
encrypt64 : HashFunction -> String -> String -> String
encrypt64 =
encrypt 64
encrypt : Int -> HashFunction -> String -> String -> String
encrypt blockSize hasher message key =
let
keySize =
String.length key
keyWithCorrectSize =
if keySize > blockSize then
hexStringToUtf8String (hasher key)
else if keySize < blockSize then
String.padRight blockSize (Char.fromCode 0) key
else
key
keyCodePoints =
keyWithCorrectSize
|> String.toList
|> List.map Char.toCode
partA =
keyCodePoints
|> List.map (Bitwise.xor 54 >> Char.fromCode)
|> String.fromList
partB =
keyCodePoints
|> List.map (Bitwise.xor 92 >> Char.fromCode)
|> String.fromList
in
message
|> String.append partA
|> hasher
|> hexStringToUtf8String
|> String.append partB
|> hasher
-- Utils
hexStringToUtf8String : String -> String
hexStringToUtf8String input =
input
|> String.toList
|> List.Extra.greedyGroupsOf 2
|> List.map (String.fromList >> hexStringToUtf8Char)
|> String.fromList
hexStringToUtf8Char : String -> Char
hexStringToUtf8Char input =
case Hex.fromString input of
Ok v ->
Char.fromCode v
Err err ->
Debug.crash err
You can find the related code here: https://github.com/icidasset/ongaku-ryoho/blob/master/src/App/Sources/Crypto/Hmac.elm (which includes doc tests)
edit: To be more clear... my current code here doesn't output a valid HMAC,
and I would like to know why.
Looking at the Elm SHA library, I think the problem (or at least a problem) is that the output from the hash is hex encoded. HMAC calls the hash function twice, feeding the first output back into the second call, and this needs to be the raw SHA bytes, rather than a hex string.
So you need to decode the hex output from the first call to hasher, after it is applied to partA.

OCaml - how to see module's interface?

Is it possible to see the interface of a loaded module in interactive OCaml? I have (unsuccessfully) tried searching for such a possibility, and online docs/sources are not what I am looking for.
The standard trick for this is to define a synonym for the module, which induces the toplevel to list the interface.
$ ocaml
OCaml version 4.00.1
# #load "str.cma";;
# module S = Str;;
module S :
sig
type regexp = Str.regexp
val regexp : string -> regexp
val regexp_case_fold : string -> regexp
val quote : string -> string
val regexp_string : string -> regexp
val regexp_string_case_fold : string -> regexp
val string_match : regexp -> string -> int -> bool
. . .
val first_chars : string -> int -> string
val last_chars : string -> int -> string
end
Update
(Note that this answer is from 2013. Recent revisions of OCaml provide a toplevel directive to show a module interface:
# #show_module Str;;
module Str :
sig
type regexp
val regexp : string -> regexp
. . .
val first_chars : string -> int -> string
val last_chars : string -> int -> string
end
So the semi-clever workaround is no longer required.
(There are many new directives. Type #help;; at toplevel to get a list.)
Both utop and ocaml interpreters added the #show directive since a moment. It does exactly what you want, as in the following example :
│ Welcome to utop version 1.19.3 (using OCaml version 4.04.0) │
└──────────────────────────────────────────────────────────────┘
Type #utop_help for help about using utop.
─( 15:12:33 )─< command 0 >──────────────────────────────────────{ counter: 0 }─
utop # #show List;;
module List :
sig
val length : 'a list -> int
val cons : 'a -> 'a list -> 'a list
val hd : 'a list -> 'a
...
val fast_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val sort_uniq : ('a -> 'a -> int) -> 'a list -> 'a list
val merge : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
end
PS:i'm using 4.04 version but i know that it also works for 4.03.> and maybe before that too.
In OCaml toplevel version 4.04.0, the trick of defining a module's synonym works no more:
# module L = List;;
module L = List
#
but you can use the include directive:
# module L = struct include List end;;
module L :
sig
val length : 'a list -> int
val cons : 'a -> 'a list -> 'a list
val hd : 'a list -> 'a
val tl : 'a list -> 'a list
val nth : 'a list -> int -> 'a
val rev : 'a list -> 'a list
...
val sort_uniq : ('a -> 'a -> int) -> 'a list -> 'a list
val merge : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
end
#