具有最长风格的应用行为的Ziplists

时间:2016-11-24 17:08:04

标签: haskell applicative

在Haskell中是否可以定义类似于ziplist的类型,其中操作a <*> b将生成与a和{{的最长一样长的列表1}}。

很明显,在这种情况下,我们必须假设ba是类似Monoid的列表,所以暂定声明是:

b

显然不会进行类型检查。另一种尝试性方法是使用具有约束构造函数的GADT,类似于

   instance Monoid a => Applicative (ZList a) where ...

但后来我陷入了使其成为Functor的阶段,因为我们不能保证在 data ZList a where Z:: ZList a S:: Monoid a => a-> (ZList a) -> (ZList a) 中,b将是Monoid。

显然,这个问题延伸到更广泛的代数数据类型,我们想要定义这些数据类型&#34;逐点&#34;我们生成的输出形式类似于参数形状的 union 的应用行为。

2 个答案:

答案 0 :(得分:2)

首先,您真正想要的可能是Default,而不是Monoid - 您对mappend毫无用处。

我认为Applicative本身无法做出任何有用的事情。也就是说,我可以定义一个(<*>)版本(称为(<#>)),其中包含额外的约束,让我可以按照我的想法行事。

为什么制作新数据类型没有意义

首先,假设我们 采取ExistentialQuantification路线,希望将我们的约束推送到data并拥有Functor和{{的合法实例1}}。一旦我们尝试定义Applicative

,这就会爆发
fmap

所以,在结算的情况下,让我们坚持使用{-# LANGUAGE ExistentialQuantification #-} data ZipMonList a = Default a => ZipMonList [a] -- Woops, we still need a constraint for `Default b` fmap :: Default b => (a -> b) -> ZipMonList a -> ZipMonList b fmap f (ZipMonList xs) = ZipMonList (f xs) 类型(因为我们想要相同的ZipList)并且只定义(<$>)的新约束版本,叫(<*>)

(<#>)

设置(<#>)

基础ZipList s ZipList(<*>)功能。我们需要zipWith类似的东西,但这会扩展列表。然后,(<#>)看起来很像(<#>)

(<*>)

我可以对元组进行测试:

import Control.Applicative (ZipList(..))
import Data.Default

-- Like 'zipWith', but has maximum length
zipWith' :: (Default a, Default b) => (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f []     []     = []
zipWith' f (x:xs) []     = f x   def : zipWith' f xs []
zipWith' f []     (y:ys) = f def y   : zipWith' f [] ys
zipWith' f (x:xs) (y:ys) = f x   y   : zipWith' f xs ys

-- same fixity as <*>
infixl 4 <#> 

-- like '(<*>)', but uses 'zipWith'' instead of 'zipWith'
(<#>) :: (Default a, Default b) => ZipList (a -> b) -> ZipList a -> ZipList b
ZipList fs <#> ZipList xs = ZipList (zipWith' id fs xs)

关键点:这是 ghci> (,,) <$> ZipList [1.2,3.4,5.6,7.8,9.1] <#> ZipList [[(),()],[()],[(),(),()]] <#> ZipList [1,2,3,4] ZipList {getZipList = [(1.2,[(),()],1),(3.4,[()],2),(5.6,[(),(),()],3),(7.8,[],4),(9.1,[],0)]} ,但仍然可行。

答案 1 :(得分:1)

我只想给你一些笔记,要考虑的事情。

允许这种情况的类型类的定义称为Constrained Typeclass Problem,并且有一些方法。

我注意到您只是指定结果列表应该与两个列表中的较长列表一样长,但您还没有说明其余元素应该是什么。那时你也可以使用适用的

whirlpool shop owner

(其中:*: is functor productpublic class Client extends Application{ String name, sname; TextField userTextField = new TextField(); TextField fTextField = new TextField(); String recip; TextFlow textFlow = new TextFlow(); ScrollPane sp = new ScrollPane(); Button button = new Button("Send"); int i=0; public Parent content() { GridPane grid = new GridPane(); grid.setAlignment(Pos.CENTER); grid.setHgap(10); grid.setVgap(10); grid.setPadding(new Insets(25, 25, 25, 25)); Text scenetitle = new Text("Welcome"); scenetitle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20)); grid.add(scenetitle, 0, 0, 2, 1); Label userName = new Label("User Name:"); grid.add(userName, 0, 1); grid.add(userTextField, 1, 1); Label fName = new Label("Friend Name:"); grid.add(fName, 0, 2); grid.add(fTextField, 1, 2); Button button = new Button("Start"); DropShadow shadow = new DropShadow(); button.addEventHandler(MouseEvent.MOUSE_ENTERED, (MouseEvent e) -> { button.setEffect(shadow); }); button.addEventHandler(MouseEvent.MOUSE_EXITED, (MouseEvent e) -> { button.setEffect(null); }); button.setOnAction( e -> grid.getScene().getWindow().hide()); grid.add(button,1,6); String name; name = userTextField.getText(); System.out.println(name); recip = fTextField.getText(); System.out.println(recip); return grid; } public Parent createContent(){ textFlow.setPadding(new Insets(10)); textFlow.setLineSpacing(10); TextField textField = new TextField(); textField.setPrefSize(300,30); button.setPrefSize(80,30); VBox container = new VBox(); VBox box = new VBox(); box.getChildren().addAll(sp,textFlow); container.setPadding(new Insets(10)); container.getChildren().addAll(box, new HBox(textField, button)); VBox.setVgrow(sp, Priority.ALWAYS); VBox.setVgrow(textFlow, Priority.ALWAYS); return container; } public void start(Stage stage) throws IOException { Parent q= content(); Scene scene = new Scene(q,300,400); stage.setScene(scene); stage.setTitle("Chit-Chat"); stage.show(); if (i == 1) { VBox vb = new VBox(); vb.getChildren().addAll(textFlow); sp.setVmax(440); sp.setPrefSize(400, 300); sp.setContent(vb); sp.vvalueProperty().bind((ObservableValue<? extends Number>) vb.heightProperty()); Parent p = createContent(); Scene scene2 = new Scene(p, 400, 300); stage.setScene(scene2); stage.setTitle("Chit-Chat"); stage.show(); } } } public static void main(String[] args) throws IOException { launch(args); } } 是一个幺半群,我只是在非负数上取最大值),它跟踪了长度&#34;分开,因为剩下的元素将毫无意义。

相反,我怀疑你的意思是在某种意义上保留其余元素,即所以

ZipList :*: Const (MaxPos Int)

以及

MaxPos

所以,如果我们要填写&#34;在前一种情况下缺少元素我们应该用1填充它们,而在后者中我们应该用0填充它们。这开始向我们展示问题的不同方面;我们需要根据操作选择身份元素,或者只是单独留下&#34;其余元素(将操作限制为(*) <$> [2,3,4] <*> [4] = [8,3,4] 类型)。这看起来不太可能,探索更多内容会很有趣。这就是我现在所拥有的,抱歉。