有没有办法让函数"键入"在Elixir中实施协议?我正在使用自定义Functor
协议,并且想知道我是否可以使函数实现它(忽略Elixir类型系统的所有限制)。
实施(如果function
类型)
defimpl Category.Functor, for: function do
def fmap(f, g), do: &(g.(f.(x))
end
鉴于你可以做到
f_2x_plus_1 = &(&1 * 2) |> Functor.fmap(&(&1 + 1))
f_2x_plus_1.(1) == 3
并非我将此用于任何严肃的事情,只是想知道。
答案 0 :(得分:1)
事实证明你可以。以下是我正在处理的可能导致名为excategory
defmodule Category.Function do
def compose(f, g) do
arity_f = :erlang.fun_info(f)[:arity]
arity_g = :erlang.fun_info(g)[:arity]
case {arity_f, arity_g} do
{1, 1} ->
&(g.(f.(&1)))
arities ->
raise "Function are not of arity 1, got #{arities}"
end
end
end
defimpl Category.Functor.P, for: Function do
defdelegate map(f, g), to: Category.Function, as: :compose
end
它出现在“入门”的“协议”部分
答案 1 :(得分:1)
你的例子对我来说并没有多大意义,因为在elixir中只有一种类型的函数,但是Function是一种类型,你可以 实现协议。
defimpl Category.Functor, for: Function do
def fmap(f, g), do: &(g.(f.(&1))
end
我看到的问题是,在Elixir / Erlang中,arity非常重要,我不知道如何以直截了当的方式解释它。
答案 2 :(得分:0)
因为Erlang / Elixir是动态类型的,所以严格的答案是否定的。函数实际上仅由arity(或命名函数,模块,函数名称和arity)区分。
您可以通过Typespecs指定更多特定类型,透析器(通过dialyxer在混合任务中使用)将对此进行一些断言,但这不是编译工具链或运行时的一部分,并且不提供任何保证。并非所有违规行为都会被透析器捕获(这取决于成功输入),但这是一个良好的开端。
答案 3 :(得分:0)
我不确定为什么你需要一个Protocol
...抱歉,如果我错过了你问题中的重要内容。你可以实现一个带保护功能的功能:
defmodule Functor do
def fmap(f, g) where is_function(f) and is_function(g) do
&(g.(f.(&1)))
end
end
然后你可以写:
iex> f_2x_plus_1 = Functor.fmap(&(&1 * 2), &(&1 + 1))
#Function<0.100612233/1 in Functor.fmap/2>
...> f_2x_plus_1.(1)
3
我想我只是不确定协议会给你一个函数没有的东西。