2016-03-05 30 views
1

有没有办法让功能“类型”在Elixir中实现协议?我正在玩一个自定义的Functor协议,并想知道我是否可以使功能实现它(忽略Elixir类型系统的所有限制)。“功能”可以在Elixir中实现协议吗?

实现(如果function其中A型)将

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

以下是Elixir中的类别库https://github.com/robot-overlord/witchcraft这可能有助于了解他们已经完成的工作。 – CoderDennis

回答

0

由于Erlang/Elixir是动态输入的,严格的答案是否定的。函数实际上仅由arity(或者对于命名函数,模块,函数名称和元数据)来区分。

您可以通过Typespecs指定更多特定类型,透析器(可通过dialyxer在混合任务中使用)将对此做一些断言,但这不是编译工具链或运行库的一部分,并且不提供任何保证。并非所有的违规行为都会被透析器捕获(这是基于成功打字),但这是一个好的开始。

+0

我真的不需要关于其arity的保证。查看更新。 –

+0

虽然我不知道答案会有什么变化。如果你不能用类型描述来表达,你可能一无所有。如果你可以通过类型描述来表达它,你可以用宏做技巧来帮助你自己。 – asonge

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 

我想我只是不知道该协议得到你的函数没有按”吨。

+1

在Haskell中,Functor是一个类类,而不是具体的类型。 Elixir中最好的模拟器(以及它的工作非常好)是一个协议。所以我一直在移植一些(类别理论)类型类,如Functor,Applicative,Monad,Monoid,SemiGroup等。一个协议让我通过一个函数是基于类型的调度和可扩展性。这个想法是,你创建一个处理Monoid的库,你为你的自定义结构/类型实现了Monoid Protocol,你可以将它传递给那个模块。 –

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 

这是对入门

http://elixir-lang.org/getting-started/protocols.html

+0

那么这是什么让你?我仍然不清楚您尝试启用的语法。 –

+0

@ChrisMeyer在Haskell(和Cathegory Theory)中的一个函数是Functor(也是一个Applicative和Monad)。有用或不是我想要使用协议在Elixir中实现常见的Haskell类型类。我猜Monads不会是那种流行的en elixir,但是monoid可以是非常有用的。 –

1

您的例子并不构成一个整体的协议部分因为在elixir中只有单一类型的功能,所以对我来说很有意义,但功能是可以实现协议的类型。

defimpl Category.Functor, for: Function do 
    def fmap(f, g), do: &(g.(f.(&1)) 
end 

,我看到的问题是,元数是仙丹/二郎非常重要的,我不知道如何以简单的方式解释这一点。

+0

看到我自己的答案。它不是理想的手工检查,但我想它是唯一的方法。 –

+0

有时可以使用Kernel.apply来解决元组问题。 –

+0

嗯...但我不认为我实际上可以使用'apply',因为它的功能组成,你实际上不能评估。 –